diff --git a/.gitignore b/.gitignore index 59f507d15802..af3d4f9128b7 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,9 @@ target/ *.diff *.patch *.tmp +*.java~ +*.properties~ +*.xml~ # system ignore .DS_Store diff --git a/README b/README deleted file mode 100644 index 8610835f160e..000000000000 --- a/README +++ /dev/null @@ -1,193 +0,0 @@ -Dubbo is a distributed service framework enpowers applications with service import/export capability with high performance RPC. - -It's composed of three kernel parts: - -Remoting: a network communication framework provides sync-over-async and request-response messaging. - -Clustering: a remote procedure call abstraction with load-balancing/failover/clustering capabilities. - -Registry: a service directory framework for service registration and service event publish/subscription - -For more, please refer to: - - http://code.alibabatech.com/wiki/display/dubbo - -================================================================ -Quick Start -================================================================ - -Export remote service: - - - - - -Refer remote service: - - - - - - - -================================================================ -Source Building -================================================================ - -0. Install the git and maven command line: - - yum install git - or: apt-get install git - - cd ~ - wget http://www.apache.org/dist//maven/binaries/apache-maven-2.2.1-bin.tar.gz - tar zxvf apache-maven-2.2.1-bin.tar.gz - vi .bash_profile - - edit: export PATH=$PATH:~/apache-maven-2.2.1/bin - source .bash_profile - -1. Checkout the dubbo source code: - - cd ~ - git clone https://github.com/AlibabaTech/dubbo.git dubbo - - git checkout -b dubbo-2.4.0 - git checkout master - -2. Import the dubbo source code to eclipse project: - - cd ~/dubbo - mvn eclipse:eclipse - Eclipse -> Menu -> File -> Import -> Exsiting Projects to Workspace -> Browse -> Finish - - Context Menu -> Run As -> Java Application: - dubbo-demo-provider/src/test/java/com.alibaba.dubbo.demo.provider.DemoProvider - dubbo-demo-consumer/src/test/java/com.alibaba.dubbo.demo.consumer.DemoConsumer - dubbo-monitor-simple/src/test/java/com.alibaba.dubbo.monitor.simple.SimpleMonitor - dubbo-registry-simple/src/test/java/com.alibaba.dubbo.registry.simple.SimpleRegistry - - Edit Config: - dubbo-demo-provider/src/test/resources/dubbo.properties - dubbo-demo-consumer/src/test/resources/dubbo.properties - dubbo-monitor-simple/src/test/resources/dubbo.properties - dubbo-registry-simple/src/test/resources/dubbo.properties - -3. Build the dubbo binary package: - - cd ~/dubbo - mvn clean install -Dmaven.test.skip - cd dubbo/target - ls - -4. Install the demo provider: - - cd ~/dubbo/dubbo-demo-provider/target - tar zxvf dubbo-demo-provider-2.4.0-assembly.tar.gz - cd dubbo-demo-provider-2.4.0/bin - ./start.sh - -5. Install the demo consumer: - - cd ~/dubbo/dubbo-demo-consumer/target - tar zxvf dubbo-demo-consumer-2.4.0-assembly.tar.gz - cd dubbo-demo-consumer-2.4.0/bin - ./start.sh - cd ../logs - tail -f stdout.log - -6. Install the simple monitor: - - cd ~/dubbo/dubbo-simple-monitor/target - tar zxvf dubbo-simple-monitor-2.4.0-assembly.tar.gz - cd dubbo-simple-monitor-2.4.0/bin - ./start.sh - http://127.0.0.1:8080 - -7. Install the simple registry: - - cd ~/dubbo/dubbo-simple-registry/target - tar zxvf dubbo-simple-registry-2.4.0-assembly.tar.gz - cd dubbo-simple-registry-2.4.0/bin - ./start.sh - - cd ~/dubbo/dubbo-demo-provider/conf - vi dubbo.properties - - edit: dubbo.registry.adddress=dubbo://127.0.0.1:9090 - cd ../bin - ./restart.sh - - cd ~/dubbo/dubbo-demo-consumer/conf - vi dubbo.properties - - edit: dubbo.registry.adddress=dubbo://127.0.0.1:9090 - cd ../bin - ./restart.sh - - cd ~/dubbo/dubbo-simple-monitor/conf - vi dubbo.properties - - edit: dubbo.registry.adddress=dubbo://127.0.0.1:9090 - cd ../bin - ./restart.sh - -8. Install the zookeeper registry: - - cd ~ - wget http://www.apache.org/dist//zookeeper/zookeeper-3.3.3/zookeeper-3.3.3.tar.gz - tar zxvf zookeeper-3.3.3.tar.gz - cd zookeeper-3.3.3/conf - cp zoo_sample.cfg zoo.cfg - vi zoo.cfg - - edit: dataDir=/home/xxx/data - cd ../bin - ./zkServer.sh start - - cd ~/dubbo/dubbo-demo-provider/conf - vi dubbo.properties - - edit: dubbo.registry.adddress=zookeeper://127.0.0.1:2181 - cd ../bin - ./restart.sh - - cd ~/dubbo/dubbo-demo-consumer/conf - vi dubbo.properties - - edit: dubbo.registry.adddress=zookeeper://127.0.0.1:2181 - cd ../bin - ./restart.sh - - cd ~/dubbo/dubbo-simple-monitor/conf - vi dubbo.properties - - edit: dubbo.registry.adddress=zookeeper://127.0.0.1:2181 - cd ../bin - ./restart.sh - -9. Install the redis registry: - - cd ~ - wget http://redis.googlecode.com/files/redis-2.4.8.tar.gz - tar xzf redis-2.4.8.tar.gz - cd redis-2.4.8 - make - nohup ./src/redis-server redis.conf & - - cd ~/dubbo/dubbo-demo-provider/conf - vi dubbo.properties - - edit: dubbo.registry.adddress=redis://127.0.0.1:6379 - cd ../bin - ./restart.sh - - cd ~/dubbo/dubbo-demo-consumer/conf - vi dubbo.properties - - edit: dubbo.registry.adddress=redis://127.0.0.1:6379 - cd ../bin - ./restart.sh - - cd ~/dubbo/dubbo-simple-monitor/conf - vi dubbo.properties - - edit: dubbo.registry.adddress=redis://127.0.0.1:6379 - cd ../bin - ./restart.sh - -10. Install the admin console: - - cd ~/dubbo/dubbo-admin - mvn jetty:run -Ddubbo.registry.address=zookeeper://127.0.0.1:2181 - http://root:root@127.0.0.1:8080 - diff --git a/README.md b/README.md new file mode 100644 index 000000000000..74856b9e19bc --- /dev/null +++ b/README.md @@ -0,0 +1,202 @@ +Dubbox now means Dubbo eXtensions. If you know java, javax and dubbo, you know what dubbox is :) + +Dubbox adds features like RESTful remoting, Kyro/FST serialization, etc to the popular [dubbo service framework](http://github.com/alibaba/dubbo). It's been used by several projects of [dangdang.com](http://www.dangdang.com), which is one of the major e-commerce companies in China. + +## 主要贡献者 + +* 沈理 [当当网](http://www.dangdang.com/) shenli@dangdang.com +* 王宇轩 [当当网](http://www.dangdang.com/) wangyuxuan@dangdang.com +* 马金凯 [韩都衣舍](http://www.handu.com/) majinkai@handu.com +* Dylan 独立开发者 dinguangx@163.com +* Kangfoo 独立开发者 + +有技术问题请移步此处讨论 https://github.com/dangdangdotcom/dubbox/issues + +## Dubbox当前的主要功能 + +* **支持REST风格远程调用(HTTP + JSON/XML)**:基于非常成熟的JBoss [RestEasy](http://resteasy.jboss.org/)框架,在dubbo中实现了REST风格(HTTP + JSON/XML)的远程调用,以显著简化企业内部的跨语言交互,同时显著简化企业对外的Open API、无线API甚至AJAX服务端等等的开发。事实上,这个REST调用也使得Dubbo可以对当今特别流行的“微服务”架构提供基础性支持。 另外,REST调用也达到了比较高的性能,在基准测试下,HTTP + JSON与Dubbo 2.x默认的RPC协议(即TCP + Hessian2二进制序列化)之间只有1.5倍左右的差距,详见文档中的基准测试报告。 + +* **支持基于Kryo和FST的Java高效序列化实现**:基于当今比较知名的[Kryo](https://github.com/EsotericSoftware/kryo)和[FST](https://github.com/RuedigerMoeller/fast-serialization)高性能序列化库,为Dubbo默认的RPC协议添加新的序列化实现,并优化调整了其序列化体系,比较显著的提高了Dubbo RPC的性能,详见文档中的基准测试报告。 + +* **支持基于Jackson的JSON序列化**:基于业界应用最广泛的[Jackson](http://jackson.codehaus.org/)序列化库,为Dubbo默认的RPC协议添加新的JSON序列化实现。 + +* **支持基于嵌入式Tomcat的HTTP remoting体系**:基于嵌入式tomcat实现dubbo的HTTP remoting体系(即dubbo-remoting-http),用以逐步取代Dubbo中旧版本的嵌入式Jetty,可以显著的提高REST等的远程调用性能,并将Servlet API的支持从2.5升级到3.1。(注:除了REST,dubbo中的WebServices、Hessian、HTTP Invoker等协议都基于这个HTTP remoting体系)。 + +* **升级Spring**:将dubbo中Spring由2.x升级到目前最常用的3.x版本,减少版本冲突带来的麻烦。 + +* **升级ZooKeeper客户端**:将dubbo中的zookeeper客户端升级到最新的版本,以修正老版本中包含的bug。 + +* **支持完全基于Java代码的Dubbo配置**:基于Spring的Java Config,实现完全无XML的纯Java代码方式来配置dubbo + +* **调整Demo应用**:暂时将dubbo的demo应用调整并改写以主要演示REST功能、Dubbo协议的新序列化方式、基于Java代码的Spring配置等等。 + +* **修正了dubbo的bug** 包括配置、序列化、管理界面等等的bug。 + +**注:dubbox和dubbo 2.x是兼容的,没有改变dubbo的任何已有的功能和配置方式(除了升级了spring之类的版本)** + +## 文档资料 + +[在Dubbo中开发REST风格的远程调用(RESTful Remoting)](https://dangdangdotcom.github.io/dubbox/rest.html) + +[在Dubbo中使用高效的Java序列化(Kryo和FST)](https://dangdangdotcom.github.io/dubbox/serialization.html) + +[使用JavaConfig方式配置dubbox](https://dangdangdotcom.github.io/dubbox/java-config.html) + +[Dubbo Jackson序列化使用说明](https://dangdangdotcom.github.io/dubbox/jackson.html) + +[Demo应用简单运行指南](https://dangdangdotcom.github.io/dubbox/demo.html) + +[Dubbox@InfoQ](http://www.infoq.com/cn/news/2014/10/dubbox-open-source) + +[Dubbox Wiki](https://github.com/dangdangdotcom/dubbox/wiki) (由社区志愿者自由编辑的) + +## 版本 + +详见:https://github.com/dangdangdotcom/dubbox/releases + +* **dubbox-2.8.0**:主要支持REST风格远程调用、支持Kryo和FST序列化、升级了Spring和Zookeeper客户端、调整了demo应用等等 +* **dubbox-2.8.1**:主要支持基于嵌入式tomcat的http-remoting,优化了REST客户端性能,在REST中支持限制服务端接纳的最大HTTP连接数等等 +* **dubbox-2.8.2**: + * 支持REST中的HTTP logging,包括HTTP header的字段和HTTP body中的消息体,方便调试、日志纪录等等 + * 提供辅助类便于REST的中文处理 + * 改变使用`@Reference` annotation配置时的异常处理方式,即当用annotation配置时,过去dubbo在启动期间不抛出依赖服务找不到的异常,而是在具体调用时抛出NPE,这与用XML配置时的行为不一致。 + * 较大的充实了Dubbo REST的文档 +* **dubbox-2.8.3**: + * 在REST中支持dubbo统一的方式用bean validation annotation作参数校验(沈理) + * 在RpcContext上支持获取底层协议的Request/Response(沈理) + * 支持采用Spring的Java Config方式配置dubbo(马金凯) + * 在Dubbo协议中支持基于Jackson的json序列化(Dylan) + * 在Spring AOP代理过的对象上支持dubbo annotation配置(Dylan) + * 修正Dubbo管理界面中没有consumer时出现空指针异常(马金凯) + * 修正@Reference annotation中protocol设置不起作用的bug(沈理) + * 修正@Reference annotation放在setter方法上即会出错的bug(Dylan) + +## 依赖 + +从dubbox-2.8.4开始,所有依赖库的使用方式将和dubbo原来的一样:即如果要使用REST、Kyro、FST、Jackson等功能,需要用户自行手工添加相关的依赖。例如: + +### REST风格远程调用 + +```xml + + org.jboss.resteasy + resteasy-jaxrs + 3.0.7.Final + + + org.jboss.resteasy + resteasy-client + 3.0.7.Final + + + javax.validation + validation-api + 1.0.0.GA + + + + + org.jboss.resteasy + resteasy-jackson-provider + 3.0.7.Final + + + + + org.jboss.resteasy + resteasy-jaxb-provider + 3.0.7.Final + + + + + org.jboss.resteasy + resteasy-netty + 3.0.7.Final + + + + + org.jboss.resteasy + resteasy-jdk-http + 3.0.7.Final + + + + + org.apache.tomcat.embed + tomcat-embed-core + 8.0.11 + + + org.apache.tomcat.embed + tomcat-embed-logging-juli + 8.0.11 + +``` + +### Kyro序列化 + +```xml + + com.esotericsoftware.kryo + kryo + 2.24.0 + + + de.javakaffee + kryo-serializers + 0.26 + +``` + +### FST序列化 + +```xml + + de.ruedigermoeller + fst + 1.55 + +``` + +### Jackson序列化 + +```xml + + com.fasterxml.jackson.core + jackson-core + 2.3.3 + + + com.fasterxml.jackson.core + jackson-databind + 2.3.3 + +``` + +## FAQ(暂存) + +### Dubbox需要什么版本的JDK? + +目前最好在JDK 1.7以上运行 + +### Dubbo REST的服务能和Dubbo注册中心、监控中心集成吗? + +可以的,而且是自动集成的,也就是你在dubbo中开发的所有REST服务都会自动注册到服务册中心和监控中心,可以通过它们做管理。 + +但是,只有当REST的消费端也是基于dubbo的时候,注册中心中的许多服务治理操作才能完全起作用。而如果消费端是非dubbo的,自然不受注册中心管理,所以其中很多操作是不会对消费端起作用的。 + +### Dubbo REST中如何实现负载均衡和容错(failover)? + +如果dubbo REST的消费端也是dubbo的,则Dubbo REST和其他dubbo远程调用协议基本完全一样,由dubbo框架透明的在消费端做load balance、failover等等。 + +如果dubbo REST的消费端是非dubbo的,甚至是非java的,则最好配置服务提供端的软负载均衡机制,目前可考虑用LVS、HAProxy、 Nginx等等对HTTP请求做负载均衡。 + +### JAX-RS中重载的方法能够映射到同一URL地址吗? + +http://stackoverflow.com/questions/17196766/can-resteasy-choose-method-based-on-query-params + +### JAX-RS中作POST的方法能够接收多个参数吗? + +http://stackoverflow.com/questions/5553218/jax-rs-post-multiple-objects diff --git a/dubbo-admin/pom.xml b/dubbo-admin/pom.xml index ff5051f716ea..ec2a30be84ad 100644 --- a/dubbo-admin/pom.xml +++ b/dubbo-admin/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-parent - 2.4.3 + 2.8.4 dubbo-admin war @@ -41,16 +41,12 @@ com.alibaba.citrus citrus-webx-all - - org.springframework - spring - org.javassist javassist - org.jboss.netty + io.netty netty @@ -86,7 +82,7 @@ zkclient - com.netflix.curator + org.apache.curator curator-framework @@ -103,7 +99,7 @@ javax.servlet - servlet-api + javax.servlet-api provided diff --git a/dubbo-admin/src/main/java/com/alibaba/dubbo/governance/service/impl/ConsumerServiceImpl.java b/dubbo-admin/src/main/java/com/alibaba/dubbo/governance/service/impl/ConsumerServiceImpl.java index bd236c293293..106d3c0a1655 100644 --- a/dubbo-admin/src/main/java/com/alibaba/dubbo/governance/service/impl/ConsumerServiceImpl.java +++ b/dubbo-admin/src/main/java/com/alibaba/dubbo/governance/service/impl/ConsumerServiceImpl.java @@ -76,6 +76,8 @@ public List findAddresses() { public List findAddressesByApplication(String application) { List ret = new ArrayList(); ConcurrentMap> consumerUrls = getRegistryCache().get(Constants.CONSUMERS_CATEGORY); + if(consumerUrls == null) return ret; + for(Map.Entry> e1 : consumerUrls.entrySet()) { Map value = e1.getValue(); for(Map.Entry e2 : value.entrySet()) { diff --git a/dubbo-admin/src/main/java/com/alibaba/dubbo/governance/service/impl/RouteServiceImpl.java b/dubbo-admin/src/main/java/com/alibaba/dubbo/governance/service/impl/RouteServiceImpl.java index 8907888938c0..152b3d569573 100644 --- a/dubbo-admin/src/main/java/com/alibaba/dubbo/governance/service/impl/RouteServiceImpl.java +++ b/dubbo-admin/src/main/java/com/alibaba/dubbo/governance/service/impl/RouteServiceImpl.java @@ -72,8 +72,8 @@ public void enableRoute(Long id) { return; } - URL newRoute = oldRoute.removeParameter("enabled"); - registryService.unregister(oldRoute); + registryService.unregister(oldRoute); + URL newRoute= oldRoute.addParameter("enabled", true); registryService.register(newRoute); } diff --git a/dubbo-admin/src/main/java/com/alibaba/dubbo/governance/web/home/module/control/Menu.java b/dubbo-admin/src/main/java/com/alibaba/dubbo/governance/web/home/module/control/Menu.java index 9961e0e27019..92408bc53bd0 100644 --- a/dubbo-admin/src/main/java/com/alibaba/dubbo/governance/web/home/module/control/Menu.java +++ b/dubbo-admin/src/main/java/com/alibaba/dubbo/governance/web/home/module/control/Menu.java @@ -49,7 +49,7 @@ public void execute(HttpSession session, Context context, CookieParser parser) { context.put("bucLogoutAddress", rootContextPath.getURI("logout")); } if (! context.containsKey("helpUrl")) { - context.put("helpUrl", "http://code.alibabatech.com/wiki/display/dubbo"); + context.put("helpUrl", "https://github.com/dangdangdotcom/dubbox/wiki"); } context.put(WebConstants.CURRENT_USER_KEY, user); context.put("language", parser.getString("locale")); diff --git a/dubbo-cluster/pom.xml b/dubbo-cluster/pom.xml index fbb592f97398..ec6af560cb05 100644 --- a/dubbo-cluster/pom.xml +++ b/dubbo-cluster/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-parent - 2.4.3 + 2.8.4 dubbo-cluster jar diff --git a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/RuleConverter.java b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/RuleConverter.java new file mode 100644 index 000000000000..ec089690a42b --- /dev/null +++ b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/RuleConverter.java @@ -0,0 +1,32 @@ +/* + * Copyright 1999-2012 Alibaba Group. + * + * Licensed 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.cluster; + +import java.util.List; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.extension.SPI; + +/** + * @author kimi + */ +@SPI +public interface RuleConverter { + + List convert(URL subscribeUrl, Object source); + +} diff --git a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/directory/AbstractDirectory.java b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/directory/AbstractDirectory.java index 017af5940ae5..622cc06d03f4 100644 --- a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/directory/AbstractDirectory.java +++ b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/directory/AbstractDirectory.java @@ -1,66 +1,67 @@ -/* - * Copyright 1999-2011 Alibaba Group. - * - * Licensed 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. - */ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.cluster.directory; -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.dubbo.common.Constants; -import com.alibaba.dubbo.common.URL; -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.rpc.Invocation; -import com.alibaba.dubbo.rpc.Invoker; -import com.alibaba.dubbo.rpc.RpcException; -import com.alibaba.dubbo.rpc.cluster.Directory; -import com.alibaba.dubbo.rpc.cluster.Router; -import com.alibaba.dubbo.rpc.cluster.RouterFactory; -import com.alibaba.dubbo.rpc.cluster.router.MockInvokersSelector; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.alibaba.dubbo.common.Constants; +import com.alibaba.dubbo.common.URL; +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.rpc.Invocation; +import com.alibaba.dubbo.rpc.Invoker; +import com.alibaba.dubbo.rpc.RpcException; +import com.alibaba.dubbo.rpc.cluster.Directory; +import com.alibaba.dubbo.rpc.cluster.Router; +import com.alibaba.dubbo.rpc.cluster.RouterFactory; +import com.alibaba.dubbo.rpc.cluster.router.MockInvokersSelector; /** - * 增加router的Directory + * 增加router的Directory * * @author chao.liuc */ public abstract class AbstractDirectory implements Directory { - - // 日志输出 - private static final Logger logger = LoggerFactory.getLogger(AbstractDirectory.class); - private final URL url ; + // 日志输出 + private static final Logger logger = LoggerFactory.getLogger(AbstractDirectory.class); + + private final URL url ; private volatile boolean destroyed = false; - - private volatile URL consumerUrl ; - + + private volatile URL consumerUrl ; + private volatile List routers; public AbstractDirectory(URL url) { this(url, null); - } - - public AbstractDirectory(URL url, List routers) { - this(url, url, routers); + } + + public AbstractDirectory(URL url, List routers) { + this(url, url, routers); } public AbstractDirectory(URL url, URL consumerUrl, List routers) { if (url == null) throw new IllegalArgumentException("url == null"); - this.url = url; + this.url = url; this.consumerUrl = consumerUrl; setRouters(routers); } @@ -69,19 +70,19 @@ public List> list(Invocation invocation) throws RpcException { if (destroyed){ throw new RpcException("Directory already destroyed .url: "+ getUrl()); } - List> invokers = doList(invocation); - List localRouters = this.routers; // local reference - if (localRouters != null && localRouters.size() > 0) { - for (Router router: localRouters){ - try { + List> invokers = doList(invocation); + List localRouters = this.routers; // local reference + if (localRouters != null && localRouters.size() > 0) { + for (Router router: localRouters){ + try { if (router.getUrl() == null || router.getUrl().getParameter(Constants.RUNTIME_KEY, true)) { - invokers = router.route(invokers, getConsumerUrl(), invocation); - } - } catch (Throwable t) { - logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t); + invokers = router.route(invokers, getConsumerUrl(), invocation); + } + } catch (Throwable t) { + logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t); } - } - } + } + } return invokers; } @@ -91,38 +92,39 @@ public URL getUrl() { public List getRouters(){ return routers; - } - - public URL getConsumerUrl() { - return consumerUrl; - } - - public void setConsumerUrl(URL consumerUrl) { - this.consumerUrl = consumerUrl; - } + } + + public URL getConsumerUrl() { + return consumerUrl; + } - protected void setRouters(List routers){ - // copy list - routers = routers == null ? new ArrayList() : new ArrayList(routers); - // append url router - String routerkey = url.getParameter(Constants.ROUTER_KEY); - if (routerkey != null && routerkey.length() > 0) { - RouterFactory routerFactory = ExtensionLoader.getExtensionLoader(RouterFactory.class).getExtension(routerkey); - routers.add(routerFactory.getRouter(url)); - } - // append mock invoker selector - routers.add(new MockInvokersSelector()); + public void setConsumerUrl(URL consumerUrl) { + this.consumerUrl = consumerUrl; + } + + protected void setRouters(List routers){ + // copy list + routers = routers == null ? new ArrayList() : new ArrayList(routers); + // append url router + String routerkey = url.getParameter(Constants.ROUTER_KEY); + if (routerkey != null && routerkey.length() > 0) { + RouterFactory routerFactory = ExtensionLoader.getExtensionLoader(RouterFactory.class).getExtension(routerkey); + routers.add(routerFactory.getRouter(url)); + } + // append mock invoker selector + routers.add(new MockInvokersSelector()); + Collections.sort(routers); this.routers = routers; } - - public boolean isDestroyed() { - return destroyed; - } + + public boolean isDestroyed() { + return destroyed; + } public void destroy(){ destroyed = true; - } - - protected abstract List> doList(Invocation invocation) throws RpcException ; + } + + protected abstract List> doList(Invocation invocation) throws RpcException ; } \ No newline at end of file diff --git a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/loadbalance/AbstractLoadBalance.java b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/loadbalance/AbstractLoadBalance.java index f7adbb14eba6..8f53582e2e03 100644 --- a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/loadbalance/AbstractLoadBalance.java +++ b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/loadbalance/AbstractLoadBalance.java @@ -41,7 +41,23 @@ public Invoker select(List> invokers, URL url, Invocation invo protected abstract Invoker doSelect(List> invokers, URL url, Invocation invocation); protected int getWeight(Invoker invoker, Invocation invocation) { - return invoker.getUrl().getMethodParameter(invocation.getMethodName(), Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT); + int weight = invoker.getUrl().getMethodParameter(invocation.getMethodName(), Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT); + if (weight > 0) { + long timestamp = invoker.getUrl().getParameter(Constants.TIMESTAMP_KEY, 0L); + if (timestamp > 0L) { + int uptime = (int) (System.currentTimeMillis() - timestamp); + int warmup = invoker.getUrl().getParameter(Constants.WARMUP_KEY, Constants.DEFAULT_WARMUP); + if (uptime > 0 && uptime < warmup) { + weight = calculateWarmupWeight(uptime, warmup, weight); + } + } + } + return weight; + } + + static int calculateWarmupWeight(int uptime, int warmup, int weight) { + int ww = (int) ( (float) uptime / ( (float) warmup / (float) weight ) ); + return ww < 1 ? 1 : (ww > weight ? weight : ww); } } \ No newline at end of file diff --git a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/ClusterUtils.java b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/ClusterUtils.java index 646329edf86c..9d31824b0979 100644 --- a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/ClusterUtils.java +++ b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/ClusterUtils.java @@ -38,10 +38,22 @@ public static URL mergeUrl(URL remoteUrl, Map localMap) { //线程池配置不使用提供者的 map.remove(Constants.THREAD_NAME_KEY); + map.remove(Constants.DEFAULT_KEY_PREFIX + Constants.THREAD_NAME_KEY); + + map.remove(Constants.THREADPOOL_KEY); + map.remove(Constants.DEFAULT_KEY_PREFIX + Constants.THREADPOOL_KEY); + map.remove(Constants.CORE_THREADS_KEY); + map.remove(Constants.DEFAULT_KEY_PREFIX + Constants.CORE_THREADS_KEY); + map.remove(Constants.THREADS_KEY); + map.remove(Constants.DEFAULT_KEY_PREFIX + Constants.THREADS_KEY); + map.remove(Constants.QUEUES_KEY); + map.remove(Constants.DEFAULT_KEY_PREFIX + Constants.QUEUES_KEY); + map.remove(Constants.ALIVE_KEY); + map.remove(Constants.DEFAULT_KEY_PREFIX + Constants.ALIVE_KEY); } if (localMap != null && localMap.size() > 0) { @@ -79,7 +91,8 @@ public static URL mergeUrl(URL remoteUrl, Map localMap) { localMap.put(Constants.INVOKER_LISTENER_KEY, remoteListener + "," + localListener); } } - return remoteUrl.addParameters(map); + + return remoteUrl.clearParameters().addParameters(map); } private ClusterUtils() {} diff --git a/dubbo-cluster/src/test/java/com/alibaba/dubbo/rpc/cluster/loadbalance/LoadBalanceTest.java b/dubbo-cluster/src/test/java/com/alibaba/dubbo/rpc/cluster/loadbalance/LoadBalanceTest.java index cc09aba64e12..55e2a0417d09 100644 --- a/dubbo-cluster/src/test/java/com/alibaba/dubbo/rpc/cluster/loadbalance/LoadBalanceTest.java +++ b/dubbo-cluster/src/test/java/com/alibaba/dubbo/rpc/cluster/loadbalance/LoadBalanceTest.java @@ -28,6 +28,7 @@ import org.junit.BeforeClass; import org.junit.Test; +import com.alibaba.dubbo.common.Constants; import com.alibaba.dubbo.common.URL; import com.alibaba.dubbo.common.extension.ExtensionLoader; import com.alibaba.dubbo.rpc.Invocation; @@ -144,7 +145,24 @@ public Map getInvokeCounter(int runs,String loadbalanceName) counter.get(sinvoker).incrementAndGet(); } return counter; + } + + @Test + public void testLoadBalanceWarmup() { + Assert.assertEquals(1, AbstractLoadBalance.calculateWarmupWeight(0, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT)); + Assert.assertEquals(1, AbstractLoadBalance.calculateWarmupWeight(13, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT)); + Assert.assertEquals(1, AbstractLoadBalance.calculateWarmupWeight(6 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT)); + Assert.assertEquals(2, AbstractLoadBalance.calculateWarmupWeight(12 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT)); + Assert.assertEquals(10, AbstractLoadBalance.calculateWarmupWeight(60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT)); + Assert.assertEquals(50, AbstractLoadBalance.calculateWarmupWeight(5 * 60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT)); + Assert.assertEquals(50, AbstractLoadBalance.calculateWarmupWeight(5 * 60 * 1000 + 23, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT)); + Assert.assertEquals(50, AbstractLoadBalance.calculateWarmupWeight(5 * 60 * 1000 + 5999, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT)); + Assert.assertEquals(51, AbstractLoadBalance.calculateWarmupWeight(5 * 60 * 1000 + 6000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT)); + Assert.assertEquals(90, AbstractLoadBalance.calculateWarmupWeight(9 * 60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT)); + Assert.assertEquals(98, AbstractLoadBalance.calculateWarmupWeight(10 * 60 * 1000 - 12 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT)); + Assert.assertEquals(99, AbstractLoadBalance.calculateWarmupWeight(10 * 60 * 1000 - 6 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT)); + Assert.assertEquals(100, AbstractLoadBalance.calculateWarmupWeight(10 * 60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT)); + Assert.assertEquals(100, AbstractLoadBalance.calculateWarmupWeight(20 * 60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT)); } - } \ No newline at end of file diff --git a/dubbo-cluster/src/test/java/com/alibaba/dubbo/rpc/cluster/support/ClusterUtilsTest.java b/dubbo-cluster/src/test/java/com/alibaba/dubbo/rpc/cluster/support/ClusterUtilsTest.java new file mode 100644 index 000000000000..4c7e51a1f939 --- /dev/null +++ b/dubbo-cluster/src/test/java/com/alibaba/dubbo/rpc/cluster/support/ClusterUtilsTest.java @@ -0,0 +1,82 @@ +/* + * Copyright 1999-2012 Alibaba Group. + * + * Licensed 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.cluster.support; + +import org.junit.Assert; +import org.junit.Test; + +import com.alibaba.dubbo.common.Constants; +import com.alibaba.dubbo.common.URL; + +/** + * @author kimi + */ +public class ClusterUtilsTest { + + @Test + public void testMergeUrl() throws Exception { + URL providerURL = URL.valueOf("dubbo://localhost:55555"); + providerURL = providerURL.setPath("path") + .setUsername("username") + .setPassword("password"); + + providerURL = providerURL.addParameter(Constants.GROUP_KEY, "dubbo") + .addParameter(Constants.VERSION_KEY, "1.2.3") + .addParameter(Constants.DUBBO_VERSION_KEY, "2.3.7") + .addParameter(Constants.THREADPOOL_KEY, "fixed") + .addParameter(Constants.THREADS_KEY, Integer.MAX_VALUE) + .addParameter(Constants.THREAD_NAME_KEY, "test") + .addParameter(Constants.CORE_THREADS_KEY, Integer.MAX_VALUE) + .addParameter(Constants.QUEUES_KEY, Integer.MAX_VALUE) + .addParameter(Constants.ALIVE_KEY, Integer.MAX_VALUE) + .addParameter(Constants.DEFAULT_KEY_PREFIX + Constants.THREADS_KEY, Integer.MAX_VALUE) + .addParameter(Constants.DEFAULT_KEY_PREFIX + Constants.THREADPOOL_KEY, "fixed") + .addParameter(Constants.DEFAULT_KEY_PREFIX + Constants.CORE_THREADS_KEY, Integer.MAX_VALUE) + .addParameter(Constants.DEFAULT_KEY_PREFIX + Constants.QUEUES_KEY, Integer.MAX_VALUE) + .addParameter(Constants.DEFAULT_KEY_PREFIX + Constants.ALIVE_KEY, Integer.MAX_VALUE) + .addParameter(Constants.DEFAULT_KEY_PREFIX + Constants.THREAD_NAME_KEY, "test"); + + URL consumerURL = URL.valueOf("dubbo://localhost:55555"); + consumerURL = consumerURL.addParameter(Constants.PID_KEY, "1234"); + consumerURL = consumerURL.addParameter(Constants.THREADPOOL_KEY, "foo"); + + URL url = ClusterUtils.mergeUrl(providerURL, consumerURL.getParameters()); + + Assert.assertFalse(url.hasParameter(Constants.THREADS_KEY)); + Assert.assertFalse(url.hasParameter(Constants.DEFAULT_KEY_PREFIX + Constants.THREADS_KEY)); + + Assert.assertFalse(url.hasParameter(Constants.DEFAULT_KEY_PREFIX + Constants.THREADPOOL_KEY)); + + Assert.assertFalse(url.hasParameter(Constants.CORE_THREADS_KEY)); + Assert.assertFalse(url.hasParameter(Constants.DEFAULT_KEY_PREFIX + Constants.CORE_THREADS_KEY)); + + Assert.assertFalse(url.hasParameter(Constants.QUEUES_KEY)); + Assert.assertFalse(url.hasParameter(Constants.DEFAULT_KEY_PREFIX + Constants.QUEUES_KEY)); + + Assert.assertFalse(url.hasParameter(Constants.ALIVE_KEY)); + Assert.assertFalse(url.hasParameter(Constants.DEFAULT_KEY_PREFIX + Constants.ALIVE_KEY)); + + Assert.assertFalse(url.hasParameter(Constants.THREAD_NAME_KEY)); + Assert.assertFalse(url.hasParameter(Constants.DEFAULT_KEY_PREFIX + Constants.THREAD_NAME_KEY)); + + Assert.assertEquals(url.getPath(), "path"); + Assert.assertEquals(url.getUsername(), "username"); + Assert.assertEquals(url.getPassword(), "password"); + Assert.assertEquals(url.getParameter(Constants.PID_KEY), "1234"); + Assert.assertEquals(url.getParameter(Constants.THREADPOOL_KEY), "foo"); + } + +} diff --git a/dubbo-common/pom.xml b/dubbo-common/pom.xml index 809b17d72cba..0d5e9f761de7 100644 --- a/dubbo-common/pom.xml +++ b/dubbo-common/pom.xml @@ -14,57 +14,77 @@ - limitations under the License. --> - 4.0.0 - - com.alibaba - dubbo-parent - 2.4.3 - - dubbo-common - jar - ${project.artifactId} - The common module of dubbo project - - true - - - - org.slf4j - slf4j-api - provided - - - commons-logging - commons-logging-api - provided - - - log4j - log4j - - - org.javassist - javassist - - - com.alibaba - hessian-lite - - - com.alibaba - fastjson - provided - - - org.jvnet.sorcerer - sorcerer-javac - provided - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + 4.0.0 + + com.alibaba + dubbo-parent + 2.8.4 + + dubbo-common + jar + ${project.artifactId} + The common module of dubbo project + + true + + + + org.slf4j + slf4j-api + provided + + + commons-logging + commons-logging-api + provided + + + log4j + log4j + + + org.javassist + javassist + + + com.alibaba + hessian-lite + + + com.alibaba + fastjson + provided + + + org.jvnet.sorcerer + sorcerer-javac + provided + cglib cglib-nodep test - + + com.esotericsoftware.kryo + kryo + provided + + + de.javakaffee + kryo-serializers + provided + + + de.ruedigermoeller + fst + provided + + + com.fasterxml.jackson.core + jackson-databind + provided + + \ No newline at end of file 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 82af4beb9461..2c712237bc62 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 @@ -118,6 +118,8 @@ public class Constants { public static final int DEFAULT_THREADS = 200; + public static final boolean DEFAULT_KEEP_ALIVE = true; + public static final int DEFAULT_QUEUES = 0; public static final int DEFAULT_ALIVE = 60 * 1000; @@ -134,6 +136,8 @@ public class Constants { public static final int DEFAULT_CONNECT_TIMEOUT = 3000; + public static final int DEFAULT_REGISTRY_CONNECT_TIMEOUT = 5000; + public static final int DEFAULT_RETRIES = 2; // default buffer size is 8k. @@ -260,6 +264,16 @@ public class Constants { public static final String SERIALIZATION_KEY = "serialization"; + // modified by lishen + public static final String EXTENSION_KEY = "extension"; + + // modified by lishen + public static final String KEEP_ALIVE_KEY = "keepalive"; + + // modified by lishen + // TODO change to a better name + public static final String OPTIMIZER_KEY = "optimizer"; + public static final String EXCHANGER_KEY = "exchanger"; public static final String TRANSPORTER_KEY = "transporter"; @@ -295,6 +309,10 @@ public class Constants { public static final String PID_KEY = "pid"; public static final String TIMESTAMP_KEY = "timestamp"; + + public static final String WARMUP_KEY = "warmup"; + + public static final int DEFAULT_WARMUP = 10 * 60 * 1000; public static final String CHECK_KEY = "check"; @@ -324,7 +342,7 @@ public class Constants { public static final String HESSIAN_VERSION_KEY = "hessian.version"; - public static final String DISPATHER_KEY = "dispather"; + public static final String DISPATCHER_KEY = "dispatcher"; public static final String CHANNEL_HANDLER_KEY = "channel.handler"; @@ -573,6 +591,8 @@ public class Constants { public static final String GENERIC_SERIALIZATION_DEFAULT = "true"; + public static final String GENERIC_SERIALIZATION_BEAN = "bean"; + /* * private Constants(){ } */ 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 70b37e6cb903..80ee7a652496 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 @@ -16,6 +16,7 @@ package com.alibaba.dubbo.common; import java.net.URL; +import java.security.CodeSource; import java.util.Enumeration; import java.util.HashSet; import java.util.Set; @@ -75,42 +76,52 @@ public static String getVersion(Class cls, String defaultVersion) { } if (version == null || version.length() == 0) { // 如果规范中没有版本号,基于jar包名获取版本号 - String file = cls.getProtectionDomain().getCodeSource().getLocation().getFile(); - if (file != null && file.length() > 0 && file.endsWith(".jar")) { - file = file.substring(0, file.length() - 4); - int i = file.lastIndexOf('/'); - if (i >= 0) { - file = file.substring(i + 1); - } - i = file.indexOf("-"); - if (i >= 0) { - file = file.substring(i + 1); - } - while (file.length() > 0 && ! Character.isDigit(file.charAt(0))) { + CodeSource codeSource = cls.getProtectionDomain().getCodeSource(); + if(codeSource == null) { + logger.info("No codeSource for class " + cls.getName() + " when getVersion, use default version " + defaultVersion); + } + else { + String file = codeSource.getLocation().getFile(); + if (file != null && file.length() > 0 && file.endsWith(".jar")) { + file = file.substring(0, file.length() - 4); + int i = file.lastIndexOf('/'); + if (i >= 0) { + file = file.substring(i + 1); + } i = file.indexOf("-"); if (i >= 0) { file = file.substring(i + 1); - } else { - break; } + while (file.length() > 0 && ! Character.isDigit(file.charAt(0))) { + i = file.indexOf("-"); + if (i >= 0) { + file = file.substring(i + 1); + } else { + break; + } + } + version = file; } - version = file; } } // 返回版本号,如果为空返回缺省版本号 return version == null || version.length() == 0 ? defaultVersion : version; } catch (Throwable e) { // 防御性容错 // 忽略异常,返回缺省版本号 - logger.error(e.getMessage(), e); + logger.error("return default version, ignore exception " + e.getMessage(), e); return defaultVersion; } } + public static void checkDuplicate(Class cls, boolean failOnError) { + checkDuplicate(cls.getName().replace('.', '/') + ".class", failOnError); + } + public static void checkDuplicate(Class cls) { - checkDuplicate(cls.getName().replace('.', '/') + ".class"); + checkDuplicate(cls, false); } - public static void checkDuplicate(String path) { + public static void checkDuplicate(String path, boolean failOnError) { try { // 在ClassPath搜文件 Enumeration urls = ClassHelper.getCallerClassLoader(Version.class).getResources(path); @@ -126,7 +137,12 @@ public static void checkDuplicate(String path) { } // 如果有多个,就表示重复 if (files.size() > 1) { - logger.error("Duplicate class " + path + " in " + files.size() + " jar " + files); + String error = "Duplicate class " + path + " in " + files.size() + " jar " + files; + if (failOnError) { + throw new IllegalStateException(error); + } else { + logger.error(error); + } } } catch (Throwable e) { // 防御性容错 logger.error(e.getMessage(), e); diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/beanutil/JavaBeanAccessor.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/beanutil/JavaBeanAccessor.java new file mode 100644 index 000000000000..f01442585c7a --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/beanutil/JavaBeanAccessor.java @@ -0,0 +1,38 @@ +/* + * Copyright 1999-2012 Alibaba Group. + * + * Licensed 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.beanutil; + +/** + * @author kimi + */ +public enum JavaBeanAccessor { + + /** Field accessor. */ + FIELD, + /** Method accessor.*/ + METHOD, + /** Method prefer to field. */ + ALL; + + public static boolean isAccessByMethod(JavaBeanAccessor accessor) { + return METHOD.equals(accessor) || ALL.equals(accessor); + } + + public static boolean isAccessByField(JavaBeanAccessor accessor) { + return FIELD.equals(accessor) || ALL.equals(accessor); + } + +} diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/beanutil/JavaBeanDescriptor.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/beanutil/JavaBeanDescriptor.java new file mode 100644 index 000000000000..376ebb43ff49 --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/beanutil/JavaBeanDescriptor.java @@ -0,0 +1,219 @@ +/* + * Copyright 1999-2012 Alibaba Group. + * + * Licensed 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.beanutil; + +import java.io.Serializable; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author kimi + */ +public final class JavaBeanDescriptor implements Serializable, Iterable> { + + private static final long serialVersionUID = -8505586483570518029L; + + public static final int TYPE_CLASS = 1; + + public static final int TYPE_ENUM = 2; + + public static final int TYPE_COLLECTION = 3; + + public static final int TYPE_MAP = 4; + + public static final int TYPE_ARRAY = 5; + + /** @see com.alibaba.dubbo.common.utils.ReflectUtils#isPrimitive(Class) */ + public static final int TYPE_PRIMITIVE = 6; + + public static final int TYPE_BEAN = 7; + + private static final String ENUM_PROPERTY_NAME = "name"; + + private static final String CLASS_PROPERTY_NAME = "name"; + + private static final String PRIMITIVE_PROPERTY_VALUE = "value"; + + /** + * Used to define a type is valid. + * @see #isValidType(int) + */ + private static final int TYPE_MAX = TYPE_BEAN; + + /** + * Used to define a type is valid. + * @see #isValidType(int) + */ + private static final int TYPE_MIN = TYPE_CLASS; + + private String className; + + private int type; + + private Map properties = new LinkedHashMap(); + + public JavaBeanDescriptor() {} + + public JavaBeanDescriptor(String className, int type) { + notEmpty(className, "class name is empty"); + if (!isValidType(type)) { + throw new IllegalArgumentException( + new StringBuilder(16).append("type [ ") + .append(type).append(" ] is unsupported").toString()); + } + + this.className = className; + this.type = type; + } + + public void setClassName(String className) { + this.className = className; + } + + public void setType(int type) { + this.type = type; + } + + public boolean isClassType() { + return TYPE_CLASS == type; + } + + public boolean isEnumType() { + return TYPE_ENUM == type; + } + + public boolean isCollectionType() { + return TYPE_COLLECTION == type; + } + + public boolean isMapType() { + return TYPE_MAP == type; + } + + public boolean isArrayType() { + return TYPE_ARRAY == type; + } + + public boolean isPrimitiveType() { + return TYPE_PRIMITIVE == type; + } + + public boolean isBeanType() { + return TYPE_BEAN == type; + } + + public int getType() { + return type; + } + + public String getClassName() { + return className; + } + + public Object setProperty(Object propertyName, Object propertyValue) { + notNull(propertyName, "Property name is null"); + + Object oldValue = properties.put(propertyName, propertyValue); + return oldValue; + } + + public String setEnumNameProperty(String name) { + if (isEnumType()) { + Object result = setProperty(ENUM_PROPERTY_NAME, name); + return result == null ? null : result.toString(); + } + throw new IllegalStateException("The instance is not a enum wrapper"); + } + + public String getEnumPropertyName() { + if (isEnumType()) { + Object result = getProperty(ENUM_PROPERTY_NAME).toString(); + return result == null ? null : result.toString(); + } + throw new IllegalStateException("The instance is not a enum wrapper"); + } + + public String setClassNameProperty(String name) { + if (isClassType()) { + Object result = setProperty(CLASS_PROPERTY_NAME, name); + return result == null ? null : result.toString(); + } + throw new IllegalStateException("The instance is not a class wrapper"); + } + + public String getClassNameProperty() { + if (isClassType()) { + Object result = getProperty(CLASS_PROPERTY_NAME); + return result == null ? null : result.toString(); + } + throw new IllegalStateException("The instance is not a class wrapper"); + } + + public Object setPrimitiveProperty(Object primitiveValue) { + if (isPrimitiveType()) { + return setProperty(PRIMITIVE_PROPERTY_VALUE, primitiveValue); + } + throw new IllegalStateException("The instance is not a primitive type wrapper"); + } + + public Object getPrimitiveProperty() { + if (isPrimitiveType()) { + return getProperty(PRIMITIVE_PROPERTY_VALUE); + } + throw new IllegalStateException("The instance is not a primitive type wrapper"); + } + + public Object getProperty(Object propertyName) { + notNull(propertyName, "Property name is null"); + Object propertyValue = properties.get(propertyName); + return propertyValue; + } + + public boolean containsProperty(Object propertyName) { + notNull(propertyName, "Property name is null"); + return properties.containsKey(propertyName); + } + + public Iterator> iterator() { + return properties.entrySet().iterator(); + } + + public int propertySize() { + return properties.size(); + } + + private boolean isValidType(int type) { + return TYPE_MIN <= type && type <= TYPE_MAX; + } + + private void notNull(Object obj, String message) { + if (obj == null) { + throw new IllegalArgumentException(message); + } + } + + private void notEmpty(String string, String message) { + if (isEmpty(string)) { + throw new IllegalArgumentException(message); + } + } + + private boolean isEmpty(String string) { + return string == null || "".equals(string.trim()); + } +} diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/beanutil/JavaBeanSerializeUtil.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/beanutil/JavaBeanSerializeUtil.java new file mode 100644 index 000000000000..0052d74a27ae --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/beanutil/JavaBeanSerializeUtil.java @@ -0,0 +1,467 @@ +/* + * Copyright 1999-2012 Alibaba Group. + * + * Licensed 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.beanutil; + +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.Map; + +import com.alibaba.dubbo.common.logger.Logger; +import com.alibaba.dubbo.common.logger.LoggerFactory; +import com.alibaba.dubbo.common.utils.LogHelper; +import com.alibaba.dubbo.common.utils.ReflectUtils; + +/** + * @author kimi + */ +public final class JavaBeanSerializeUtil { + + private static final Logger logger = LoggerFactory.getLogger(JavaBeanSerializeUtil.class); + + public static JavaBeanDescriptor serialize(Object obj) { + JavaBeanDescriptor result = serialize(obj, JavaBeanAccessor.FIELD); + return result; + } + + public static JavaBeanDescriptor serialize(Object obj, JavaBeanAccessor accessor) { + if (obj == null) { + return null; + } + if (obj instanceof JavaBeanDescriptor) { + return (JavaBeanDescriptor)obj; + } + IdentityHashMap cache = new IdentityHashMap(); + JavaBeanDescriptor result = createDescriptorIfAbsent(obj, accessor, cache); + return result; + } + + private static JavaBeanDescriptor createDescriptorForSerialize(Class cl) { + if (cl.isEnum()) { + return new JavaBeanDescriptor(cl.getName(), JavaBeanDescriptor.TYPE_ENUM); + } else if (cl.isArray()) { + return new JavaBeanDescriptor(cl.getComponentType().getName(), JavaBeanDescriptor.TYPE_ARRAY); + } else if (ReflectUtils.isPrimitive(cl)) { + return new JavaBeanDescriptor(cl.getName(), JavaBeanDescriptor.TYPE_PRIMITIVE); + } else if (Class.class.equals(cl)) { + return new JavaBeanDescriptor(Class.class.getName(), JavaBeanDescriptor.TYPE_CLASS); + } else if (Collection.class.isAssignableFrom(cl)) { + return new JavaBeanDescriptor(cl.getName(), JavaBeanDescriptor.TYPE_COLLECTION); + } else if (Map.class.isAssignableFrom(cl)) { + return new JavaBeanDescriptor(cl.getName(), JavaBeanDescriptor.TYPE_MAP); + } else { + return new JavaBeanDescriptor(cl.getName(), JavaBeanDescriptor.TYPE_BEAN); + } + } + + private static JavaBeanDescriptor createDescriptorIfAbsent(Object obj, JavaBeanAccessor accessor, IdentityHashMap cache) { + if (cache.containsKey(obj)) { + return cache.get(obj); + } else if (obj instanceof JavaBeanDescriptor) { + return (JavaBeanDescriptor)obj; + } else { + JavaBeanDescriptor result = createDescriptorForSerialize(obj.getClass()); + cache.put(obj, result); + serializeInternal(result, obj, accessor, cache); + return result; + } + } + + private static void serializeInternal(JavaBeanDescriptor descriptor, Object obj, JavaBeanAccessor accessor, IdentityHashMap cache) { + if (obj == null || descriptor == null) { + return; + } + + if (obj.getClass().isEnum()) { + descriptor.setEnumNameProperty(((Enum) obj).name()); + } else if (ReflectUtils.isPrimitive(obj.getClass())) { + descriptor.setPrimitiveProperty(obj); + } else if (Class.class.equals(obj.getClass())) { + descriptor.setClassNameProperty(((Class) obj).getName()); + } else if (obj.getClass().isArray()) { + int len = Array.getLength(obj); + for (int i = 0; i < len; i++) { + Object item = Array.get(obj, i); + if (item == null) { + descriptor.setProperty(i, null); + } else { + JavaBeanDescriptor itemDescriptor = createDescriptorIfAbsent(item, accessor, cache); + descriptor.setProperty(i, itemDescriptor); + } + } + } else if (obj instanceof Collection) { + Collection collection = (Collection) obj; + int index = 0; + for (Object item : collection) { + if (item == null) { + descriptor.setProperty(index++, null); + } else { + JavaBeanDescriptor itemDescriptor = createDescriptorIfAbsent(item, accessor, cache); + descriptor.setProperty(index++, itemDescriptor); + } + } + } else if (obj instanceof Map) { + Map map = (Map) obj; + for (Object key : map.keySet()) { + Object value = map.get(key); + Object keyDescriptor = key == null ? null : createDescriptorIfAbsent(key, accessor, cache); + Object valueDescriptor = value == null ? null : createDescriptorIfAbsent(value, accessor, cache); + descriptor.setProperty(keyDescriptor, valueDescriptor); + } // ~ end of loop map + } else { + if (JavaBeanAccessor.isAccessByMethod(accessor)) { + Map methods = ReflectUtils.getBeanPropertyReadMethods(obj.getClass()); + for (Map.Entry entry : methods.entrySet()) { + try { + Object value = entry.getValue().invoke(obj); + if (value == null) { + continue; + } + JavaBeanDescriptor valueDescriptor = createDescriptorIfAbsent(value, accessor, cache); + descriptor.setProperty(entry.getKey(), valueDescriptor); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } // ~ end of loop method map + } // ~ end of if (JavaBeanAccessor.isAccessByMethod(accessor)) + + if (JavaBeanAccessor.isAccessByField(accessor)) { + Map fields = ReflectUtils.getBeanPropertyFields(obj.getClass()); + for (Map.Entry entry : fields.entrySet()) { + if (!descriptor.containsProperty(entry.getKey())) { + try { + Object value = entry.getValue().get(obj); + if (value == null) { + continue; + } + JavaBeanDescriptor valueDescriptor = createDescriptorIfAbsent(value, accessor, cache); + descriptor.setProperty(entry.getKey(), valueDescriptor); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + } // ~ end of loop field map + } // ~ end of if (JavaBeanAccessor.isAccessByField(accessor)) + + } // ~ end of else + + } // ~ end of method serializeInternal + + public static Object deserialize(JavaBeanDescriptor beanDescriptor) { + Object result = deserialize( + beanDescriptor, + Thread.currentThread().getContextClassLoader()); + return result; + } + + public static Object deserialize(JavaBeanDescriptor beanDescriptor, ClassLoader loader) { + if (beanDescriptor == null) { + return null; + } + IdentityHashMap cache = new IdentityHashMap(); + Object result = instantiateForDeserialize(beanDescriptor, loader, cache); + deserializeInternal(result, beanDescriptor, loader, cache); + return result; + } + + private static void deserializeInternal(Object result, JavaBeanDescriptor beanDescriptor, ClassLoader loader, IdentityHashMap cache) { + if (beanDescriptor.isEnumType() || beanDescriptor.isClassType() || beanDescriptor.isPrimitiveType()) { + return; + } + + if (beanDescriptor.isArrayType()) { + int index = 0; + for (Map.Entry entry : beanDescriptor) { + Object item = entry.getValue(); + if (item instanceof JavaBeanDescriptor) { + JavaBeanDescriptor itemDescriptor = (JavaBeanDescriptor) entry.getValue(); + item = instantiateForDeserialize(itemDescriptor, loader, cache); + deserializeInternal(item, itemDescriptor, loader, cache); + } + Array.set(result, index++, item); + } + } else if (beanDescriptor.isCollectionType()) { + Collection collection = (Collection) result; + for (Map.Entry entry : beanDescriptor) { + Object item = entry.getValue(); + if (item instanceof JavaBeanDescriptor) { + JavaBeanDescriptor itemDescriptor = (JavaBeanDescriptor) entry.getValue(); + item = instantiateForDeserialize(itemDescriptor, loader, cache); + deserializeInternal(item, itemDescriptor, loader, cache); + } + collection.add(item); + } + } else if (beanDescriptor.isMapType()) { + Map map = (Map) result; + for (Map.Entry entry : beanDescriptor) { + Object key = entry.getKey(); + Object value = entry.getValue(); + if (key != null && key instanceof JavaBeanDescriptor) { + JavaBeanDescriptor keyDescriptor = (JavaBeanDescriptor) entry.getKey(); + key = instantiateForDeserialize(keyDescriptor, loader, cache); + deserializeInternal(key, keyDescriptor, loader, cache); + } + if (value != null && value instanceof JavaBeanDescriptor) { + JavaBeanDescriptor valueDescriptor = (JavaBeanDescriptor) entry.getValue(); + value = instantiateForDeserialize(valueDescriptor, loader, cache); + deserializeInternal(value, valueDescriptor, loader, cache); + } + map.put(key, value); + } + } else if (beanDescriptor.isBeanType()) { + for (Map.Entry entry : beanDescriptor) { + String property = entry.getKey().toString(); + Object value = entry.getValue(); + if (value == null) { + continue; + } + + if (value instanceof JavaBeanDescriptor) { + JavaBeanDescriptor valueDescriptor = (JavaBeanDescriptor) entry.getValue(); + value = instantiateForDeserialize(valueDescriptor, loader, cache); + deserializeInternal(value, valueDescriptor, loader, cache); + } + + Method method = getSetterMethod(result.getClass(), property, value.getClass()); + boolean setByMethod = false; + try { + if (method != null) { + method.invoke(result, value); + setByMethod = true; + } + } catch (Exception e) { + LogHelper.warn(logger, "Failed to set property through method " + method, e); + } + + if (!setByMethod) { + try { + Field field = result.getClass().getField(property); + if (field != null) { + field.set(result, value); + } + } catch (NoSuchFieldException e1) { + LogHelper.warn(logger, "Failed to set field value", e1); + } catch (IllegalAccessException e1) { + LogHelper.warn(logger, "Failed to set field value", e1); + } + } + } + } else { + throw new IllegalArgumentException("Unsupported type " + beanDescriptor.getClassName() + ":" + beanDescriptor.getType()); + } + } + + private static Method getSetterMethod(Class cls, String property, Class valueCls) { + String name = "set" + property.substring(0, 1).toUpperCase() + property.substring(1); + Method method = null; + try { + method = cls.getMethod(name, valueCls); + } catch (NoSuchMethodException e) { + for (Method m : cls.getMethods()) { + if (ReflectUtils.isBeanPropertyWriteMethod(m) + && m.getName().equals(name)) { + method = m; + } + } + } + if (method != null) { + method.setAccessible(true); + } + return method; + } + + private static Object instantiate(Class cl) throws Exception { + Constructor[] constructors = cl.getDeclaredConstructors(); + Constructor constructor = null; + int argc = Integer.MAX_VALUE; + for (Constructor c : constructors) { + if (c.getParameterTypes().length < argc) { + argc = c.getParameterTypes().length; + constructor = c; + } + } + + if (constructor != null) { + Class[] paramTypes = constructor.getParameterTypes(); + Object[] constructorArgs = new Object[paramTypes.length]; + for (int i = 0; i < constructorArgs.length; i++) { + constructorArgs[i] = getConstructorArg(paramTypes[i]); + } + try { + constructor.setAccessible(true); + return constructor.newInstance(constructorArgs); + } catch (InstantiationException e) { + LogHelper.warn(logger, e.getMessage(), e); + } catch (IllegalAccessException e) { + LogHelper.warn(logger, e.getMessage(), e); + } catch (InvocationTargetException e) { + LogHelper.warn(logger, e.getMessage(), e); + } + } + + return cl.newInstance(); + } + + private static Object getConstructorArg(Class cl) { + if (boolean.class.equals(cl) || Boolean.class.equals(cl)) { + return Boolean.FALSE; + } else if (byte.class.equals(cl) || Byte.class.equals(cl)) { + return Byte.valueOf((byte) 0); + } else if (short.class.equals(cl) || Short.class.equals(cl)) { + return Short.valueOf((short) 0); + } else if (int.class.equals(cl) || Integer.class.equals(cl)) { + return Integer.valueOf(0); + } else if (long.class.equals(cl) || Long.class.equals(cl)) { + return Long.valueOf(0L); + } else if (float.class.equals(cl) || Float.class.equals(cl)) { + return Float.valueOf((float) 0); + } else if (double.class.equals(cl) || Double.class.equals(cl)) { + return Double.valueOf((double) 0); + } else if (char.class.equals(cl) || Character.class.equals(cl)) { + return new Character((char) 0); + } else { + return null; + } + } + + private static Object instantiateForDeserialize(JavaBeanDescriptor beanDescriptor, ClassLoader loader, IdentityHashMap cache) { + if (cache.containsKey(beanDescriptor)) { + return cache.get(beanDescriptor); + } + Object result = null; + if (beanDescriptor.isClassType()) { + try { + result = name2Class(loader, beanDescriptor.getClassNameProperty()); + return result; + } catch (ClassNotFoundException e) { + throw new RuntimeException(e.getMessage(), e); + } + } else if (beanDescriptor.isEnumType()) { + try { + Class enumType = name2Class(loader, beanDescriptor.getClassName()); + Method method = getEnumValueOfMethod(enumType); + result = method.invoke(null, enumType, beanDescriptor.getEnumPropertyName()); + return result; + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } else if (beanDescriptor.isPrimitiveType()) { + result = beanDescriptor.getPrimitiveProperty(); + return result; + } else if (beanDescriptor.isArrayType()) { + Class componentType; + try { + componentType = name2Class(loader, beanDescriptor.getClassName()); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e.getMessage(), e); + } + result = Array.newInstance(componentType, beanDescriptor.propertySize()); + cache.put(beanDescriptor, result); + } else try { + Class cl = name2Class(loader, beanDescriptor.getClassName()); + result = instantiate(cl); + cache.put(beanDescriptor, result); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e.getMessage(), e); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + + return result; + } + + private static final Map> TYPES = new HashMap>(); + + static { + TYPES.put(boolean.class.getName(), boolean.class); + TYPES.put(byte.class.getName(), byte.class); + TYPES.put(short.class.getName(), short.class); + TYPES.put(int.class.getName(), int.class); + TYPES.put(long.class.getName(), long.class); + TYPES.put(float.class.getName(), float.class); + TYPES.put(double.class.getName(), double.class); + TYPES.put(void.class.getName(), void.class); + TYPES.put("Z", boolean.class); + TYPES.put("B", byte.class); + TYPES.put("C", char.class); + TYPES.put("D", double.class); + TYPES.put("F", float.class); + TYPES.put("I", int.class); + TYPES.put("J", long.class); + TYPES.put("S", short.class); + } + + private static final String ARRAY_PREFIX = "["; + + private static final String REFERENCE_TYPE_PREFIX = "L"; + + private static final String REFERENCE_TYPE_SUFFIX = ";"; + + /** + * 把 Class.forName 的返回值转换为 Class. + * + * @param name Class.getName() + * + * @return Class + * + * @throws ClassNotFoundException Class.forName + */ + public static Class name2Class(ClassLoader loader, String name) throws ClassNotFoundException { + if (TYPES.containsKey(name)) { + return TYPES.get(name); + } + if (isArray(name)) { + int dimension = 0; + while (isArray(name)) { + ++dimension; + name = name.substring(1); + } + Class type = name2Class(loader, name); + int[] dimensions = new int[dimension]; + for (int i = 0; i < dimension; i++) { + dimensions[i] = 0; + } + return Array.newInstance(type, dimensions).getClass(); + } + if (isReferenceType(name)) { + name = name.substring(1, name.length() - 1); + } + return Class.forName(name, false, loader); + } + + private static boolean isArray(String type) { + return type != null && type.startsWith(ARRAY_PREFIX); + } + + private static boolean isReferenceType(String type) { + return type != null + && type.startsWith(REFERENCE_TYPE_PREFIX) + && type.endsWith(REFERENCE_TYPE_SUFFIX); + } + + private static Method getEnumValueOfMethod(Class cl) throws NoSuchMethodException { + return cl.getMethod("valueOf", Class.class, String.class); + } + + private JavaBeanSerializeUtil() { + } + +} diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/bytecode/ClassGenerator.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/bytecode/ClassGenerator.java index 36a9443e58fc..84b78e50d017 100644 --- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/bytecode/ClassGenerator.java +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/bytecode/ClassGenerator.java @@ -18,6 +18,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.security.ProtectionDomain; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedList; @@ -38,7 +39,6 @@ import javassist.LoaderClassPath; import javassist.NotFoundException; -import com.alibaba.dubbo.common.utils.ClassHelper; import com.alibaba.dubbo.common.utils.ReflectUtils; /** @@ -59,7 +59,7 @@ public static interface DC{} // dynamic class tag interface. public static ClassGenerator newInstance() { - return new ClassGenerator(getClassPool(ClassHelper.getCallerClassLoader(ClassGenerator.class))); + return new ClassGenerator(getClassPool(Thread.currentThread().getContextClassLoader())); } public static ClassGenerator newInstance(ClassLoader loader) @@ -289,7 +289,11 @@ public ClassPool getClassPool() { return mPool; } - public Class toClass() + public Class toClass(){ + return toClass(getClass().getClassLoader(), getClass().getProtectionDomain()); + } + + public Class toClass(ClassLoader loader, ProtectionDomain pd) { if( mCtc != null ) mCtc.detach(); @@ -335,7 +339,7 @@ public Class toClass() } } } - return mCtc.toClass(ClassHelper.getCallerClassLoader(getClass()), null); + return mCtc.toClass(loader, pd); } catch(RuntimeException e) { diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/bytecode/Wrapper.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/bytecode/Wrapper.java index 08dff750309e..653e30e6425a 100644 --- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/bytecode/Wrapper.java +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/bytecode/Wrapper.java @@ -207,7 +207,7 @@ private static Wrapper makeWrapper(Class c) throw new IllegalArgumentException("Can not create wrapper for primitive type: " + c); String name = c.getName(); - ClassLoader cl = ClassHelper.getCallerClassLoader(Wrapper.class); + ClassLoader cl = ClassHelper.getClassLoader(c); StringBuilder c1 = new StringBuilder("public void setPropertyValue(Object o, String n, Object v){ "); StringBuilder c2 = new StringBuilder("public Object getPropertyValue(Object o, String n){ "); diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/JavassistCompiler.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/JavassistCompiler.java index ff666e262666..cc8f59a656f7 100644 --- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/JavassistCompiler.java +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/JavassistCompiler.java @@ -120,7 +120,7 @@ public Class doCompile(String name, String source) throws Throwable { } } } - return cls.toClass(ClassHelper.getCallerClassLoader(getClass()), null); + return cls.toClass(ClassHelper.getCallerClassLoader(getClass()), JavassistCompiler.class.getProtectionDomain()); } } diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/ExtensionLoader.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/ExtensionLoader.java index 453e29165555..982ab819eba5 100644 --- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/ExtensionLoader.java +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/ExtensionLoader.java @@ -369,10 +369,6 @@ public String getDefaultExtensionName() { public void addExtension(String name, Class clazz) { getExtensionClasses(); // load classes - if(cachedClasses.get().containsKey(name)) { - throw new IllegalStateException("Extension name " + - name + " already existed(Extension " + type + ")!"); - } if(!type.isAssignableFrom(clazz)) { throw new IllegalStateException("Input type " + clazz + "not implement Extension " + type); @@ -381,8 +377,26 @@ public void addExtension(String name, Class clazz) { throw new IllegalStateException("Input type " + clazz + "can not be interface!"); } - cachedNames.put(clazz, name); - cachedClasses.get().put(name, clazz); + + if(!clazz.isAnnotationPresent(Adaptive.class)) { + if(StringUtils.isBlank(name)) { + throw new IllegalStateException("Extension name is blank (Extension " + type + ")!"); + } + if(cachedClasses.get().containsKey(name)) { + throw new IllegalStateException("Extension name " + + name + " already existed(Extension " + type + ")!"); + } + + cachedNames.put(clazz, name); + cachedClasses.get().put(name, clazz); + } + else { + if(cachedAdaptiveClass != null) { + throw new IllegalStateException("Adaptive Extension already existed(Extension " + type + ")!"); + } + + cachedAdaptiveClass = clazz; + } } /** @@ -397,10 +411,6 @@ public void addExtension(String name, Class clazz) { public void replaceExtension(String name, Class clazz) { getExtensionClasses(); // load classes - if(!cachedClasses.get().containsKey(name)) { - throw new IllegalStateException("Extension name " + - name + " not existed(Extension " + type + ")!"); - } if(!type.isAssignableFrom(clazz)) { throw new IllegalStateException("Input type " + clazz + "not implement Extension " + type); @@ -410,9 +420,27 @@ public void replaceExtension(String name, Class clazz) { clazz + "can not be interface!"); } - cachedNames.put(clazz, name); - cachedClasses.get().put(name, clazz); - cachedInstances.remove(name); + if(!clazz.isAnnotationPresent(Adaptive.class)) { + if(StringUtils.isBlank(name)) { + throw new IllegalStateException("Extension name is blank (Extension " + type + ")!"); + } + if(!cachedClasses.get().containsKey(name)) { + throw new IllegalStateException("Extension name " + + name + " not existed(Extension " + type + ")!"); + } + + cachedNames.put(clazz, name); + cachedClasses.get().put(name, clazz); + cachedInstances.remove(name); + } + else { + if(cachedAdaptiveClass == null) { + throw new IllegalStateException("Adaptive Extension not existed(Extension " + type + ")!"); + } + + cachedAdaptiveClass = clazz; + cachedAdaptiveInstance.set(null); + } } @SuppressWarnings("unchecked") @@ -903,7 +931,7 @@ private String createAdaptiveExtensionClassCode() { if (i > 0) { codeBuidler.append(", "); } - codeBuidler.append(pts[i].getCanonicalName()); + codeBuidler.append(ets[i].getCanonicalName()); } } codeBuidler.append(" {"); diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/json/DefaultJacksonObjectMapperProvider.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/json/DefaultJacksonObjectMapperProvider.java new file mode 100644 index 000000000000..5b7bb5197056 --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/json/DefaultJacksonObjectMapperProvider.java @@ -0,0 +1,22 @@ +package com.alibaba.dubbo.common.json; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; + +import java.util.TimeZone; + +/** + * @author dylan + */ +public class DefaultJacksonObjectMapperProvider implements JacksonObjectMapperProvider { + @Override + public ObjectMapper getObjectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); +// objectMapper.disable(SerializationFeature.FLUSH_AFTER_WRITE_VALUE); + objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + objectMapper.setTimeZone(TimeZone.getDefault()); + return objectMapper; + } +} diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/json/J2oVisitor.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/json/J2oVisitor.java index 132d5eff2f40..1b378e09af0c 100644 --- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/json/J2oVisitor.java +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/json/J2oVisitor.java @@ -165,17 +165,19 @@ public void objectItemValue(Object obj, boolean isValue) throws ParseException } } if (mValue instanceof Throwable && "message".equals(name)) { - try { - Field field = Throwable.class.getDeclaredField("detailMessage"); - if (! field.isAccessible()) { - field.setAccessible(true); - } - field.set(mValue, obj); - } catch (NoSuchFieldException e) { - throw new ParseException(StringUtils.toString(e)); - } catch (IllegalAccessException e) { - throw new ParseException(StringUtils.toString(e)); - } + try { + Field field = Throwable.class.getDeclaredField("detailMessage"); + if (!field.isAccessible()) { + field.setAccessible(true); + } + field.set(mValue, obj); + } catch (NoSuchFieldException e) { + throw new ParseException(StringUtils.toString(e)); + } catch (IllegalAccessException e) { + throw new ParseException(StringUtils.toString(e)); + } + } else if (mValue instanceof Throwable && "suppressed".equals(name)) { // modified by lishen + // simply ignore this field for jdk 1.7+ } else if (! CLASS_PROPERTY.equals(name)) { mWrapper.setPropertyValue(mValue, name, obj); } diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/json/Jackson.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/json/Jackson.java new file mode 100644 index 000000000000..6bcd8d35cd0d --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/json/Jackson.java @@ -0,0 +1,49 @@ +package com.alibaba.dubbo.common.json; + +import com.alibaba.dubbo.common.extension.ExtensionLoader; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.TimeZone; + +/** + * @author dylan + */ +public class Jackson { + private static Logger logger = LoggerFactory.getLogger(Jackson.class); + private static ObjectMapper objectMapper; + + private static JacksonObjectMapperProvider getJacksonProvider() { + return ExtensionLoader.getExtensionLoader(JacksonObjectMapperProvider.class).getDefaultExtension(); + } + + /** + * 获取object mapper + * + * @return + */ + public static ObjectMapper getObjectMapper() { + if (objectMapper == null) { + JacksonObjectMapperProvider jacksonObjectMapperProvider = getJacksonProvider(); + if (jacksonObjectMapperProvider != null) { + objectMapper = jacksonObjectMapperProvider.getObjectMapper(); + } + } + if (objectMapper == null) { + logger.warn("load objectMapper failed, use default config."); + buildDefaultObjectMapper(); + } + return objectMapper; + } + + private static synchronized void buildDefaultObjectMapper() { + objectMapper = new ObjectMapper(); + objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); +// objectMapper.disable(SerializationFeature.FLUSH_AFTER_WRITE_VALUE); + objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + objectMapper.setTimeZone(TimeZone.getDefault()); + } +} diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/json/JacksonObjectMapperProvider.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/json/JacksonObjectMapperProvider.java new file mode 100644 index 000000000000..70524bb77c62 --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/json/JacksonObjectMapperProvider.java @@ -0,0 +1,12 @@ +package com.alibaba.dubbo.common.json; + +import com.alibaba.dubbo.common.extension.SPI; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Created by dylan on 11/12/14. + */ +@SPI("jackson") +public interface JacksonObjectMapperProvider { + public ObjectMapper getObjectMapper(); +} diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/Cleanable.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/Cleanable.java new file mode 100644 index 000000000000..1b69c56b4f94 --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/Cleanable.java @@ -0,0 +1,24 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.serialize; + +/** + * @author lishen + */ +public interface Cleanable { + + void cleanup(); +} diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/OptimizedSerialization.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/OptimizedSerialization.java new file mode 100644 index 000000000000..9216327502ad --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/OptimizedSerialization.java @@ -0,0 +1,24 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.serialize; + +/** + * Just a marker interface for now + * + * @author lishen + */ +public interface OptimizedSerialization extends Serialization { +} diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/SerializableClassRegistry.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/SerializableClassRegistry.java new file mode 100644 index 000000000000..3a09d41fe19b --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/SerializableClassRegistry.java @@ -0,0 +1,23 @@ +package com.alibaba.dubbo.common.serialize.support; + +import java.util.LinkedHashSet; +import java.util.Set; + +/** + * @author lishen + */ +public abstract class SerializableClassRegistry { + + private static final Set registrations = new LinkedHashSet(); + + /** + * only supposed to be called at startup time + */ + public static void registerClass(Class clazz) { + registrations.add(clazz); + } + + public static Set getRegisteredClasses() { + return registrations; + } +} diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/SerializationOptimizer.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/SerializationOptimizer.java new file mode 100644 index 000000000000..0f6f7a10cdfe --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/SerializationOptimizer.java @@ -0,0 +1,13 @@ +package com.alibaba.dubbo.common.serialize.support; + +import java.util.Collection; + +/** + * This class can be replaced with the contents in config file, but for now I think the class is easier to write + * + * @author lishen + */ +public interface SerializationOptimizer { + + Collection getSerializableClasses(); +} diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/fst/FstFactory.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/fst/FstFactory.java new file mode 100644 index 000000000000..38b531eadb3c --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/fst/FstFactory.java @@ -0,0 +1,53 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.serialize.support.fst; + +import com.alibaba.dubbo.common.serialize.support.SerializableClassRegistry; +import de.ruedigermoeller.serialization.FSTConfiguration; +import de.ruedigermoeller.serialization.FSTObjectInput; +import de.ruedigermoeller.serialization.FSTObjectOutput; + +import java.io.InputStream; +import java.io.OutputStream; + +/** + * @author lishen + */ +public class FstFactory { + + private static final FstFactory factory = new FstFactory(); + + private final FSTConfiguration conf = FSTConfiguration.createDefaultConfiguration(); + + + public static FstFactory getDefaultFactory() { + return factory; + } + + public FstFactory() { + for (Class clazz : SerializableClassRegistry.getRegisteredClasses()) { + conf.registerClass(clazz); + } + } + + public FSTObjectOutput getObjectOutput(OutputStream outputStream) { + return conf.getObjectOutput(outputStream); + } + + public FSTObjectInput getObjectInput(InputStream inputStream) { + return conf.getObjectInput(inputStream); + } +} diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/fst/FstObjectInput.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/fst/FstObjectInput.java new file mode 100644 index 000000000000..01fd6ea8dee9 --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/fst/FstObjectInput.java @@ -0,0 +1,95 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.serialize.support.fst; + +import com.alibaba.dubbo.common.serialize.ObjectInput; +import de.ruedigermoeller.serialization.FSTObjectInput; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Type; + +/** + * @author lishen + */ +public class FstObjectInput implements ObjectInput { + + private FSTObjectInput input; + + public FstObjectInput(InputStream inputStream) { + input = FstFactory.getDefaultFactory().getObjectInput(inputStream); + } + + public boolean readBool() throws IOException { + return input.readBoolean(); + } + + public byte readByte() throws IOException { + return input.readByte(); + } + + public short readShort() throws IOException { + return input.readShort(); + } + + public int readInt() throws IOException { + return input.readInt(); + } + + public long readLong() throws IOException { + return input.readLong(); + } + + public float readFloat() throws IOException { + return input.readFloat(); + } + + public double readDouble() throws IOException { + return input.readDouble(); + } + + public byte[] readBytes() throws IOException { + int len = input.readInt(); + if (len < 0) { + return null; + } else if (len == 0) { + return new byte[]{}; + } else { + byte[] b = new byte[len]; + input.readFully(b); + return b; + } + } + + public String readUTF() throws IOException { + return input.readUTF(); + } + + public Object readObject() throws IOException, ClassNotFoundException { + return input.readObject(); + } + + + @SuppressWarnings("unchecked") + public T readObject(Class clazz) throws IOException, ClassNotFoundException { + return (T) readObject(); + } + + @SuppressWarnings("unchecked") + public T readObject(Class clazz, Type type) throws IOException, ClassNotFoundException { + return (T) readObject(); + } +} \ No newline at end of file diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/fst/FstObjectOutput.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/fst/FstObjectOutput.java new file mode 100644 index 000000000000..ba14f041bbd0 --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/fst/FstObjectOutput.java @@ -0,0 +1,92 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.serialize.support.fst; + +import com.alibaba.dubbo.common.serialize.ObjectOutput; +import de.ruedigermoeller.serialization.FSTObjectOutput; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * @author lishen + */ +public class FstObjectOutput implements ObjectOutput { + + private FSTObjectOutput output; + + public FstObjectOutput(OutputStream outputStream) { + output = FstFactory.getDefaultFactory().getObjectOutput(outputStream); + } + + public void writeBool(boolean v) throws IOException { + output.writeBoolean(v); + } + + public void writeByte(byte v) throws IOException { + output.writeByte(v); + } + + public void writeShort(short v) throws IOException { + output.writeShort(v); + } + + public void writeInt(int v) throws IOException { + output.writeInt(v); + } + + public void writeLong(long v) throws IOException { + output.writeLong(v); + } + + public void writeFloat(float v) throws IOException { + output.writeFloat(v); + } + + public void writeDouble(double v) throws IOException { + output.writeDouble(v); + } + + public void writeBytes(byte[] v) throws IOException { + if (v == null) { + output.writeInt(-1); + } else { + writeBytes(v, 0, v.length); + } + } + + public void writeBytes(byte[] v, int off, int len) throws IOException { + if (v == null) { + output.writeInt(-1); + } else { + output.writeInt(len); + output.write(v, off, len); + } + } + + + public void writeUTF(String v) throws IOException { + output.writeUTF(v); + } + + public void writeObject(Object v) throws IOException { + output.writeObject(v); + } + + public void flushBuffer() throws IOException { + output.flush(); + } +} \ No newline at end of file diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/fst/FstSerialization.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/fst/FstSerialization.java new file mode 100644 index 000000000000..dff215b60bb5 --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/fst/FstSerialization.java @@ -0,0 +1,47 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.serialize.support.fst; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.serialize.ObjectInput; +import com.alibaba.dubbo.common.serialize.ObjectOutput; +import com.alibaba.dubbo.common.serialize.OptimizedSerialization; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * @author lishen + */ +public class FstSerialization implements OptimizedSerialization { + + public byte getContentTypeId() { + return 9; + } + + public String getContentType() { + return "x-application/fst"; + } + + public ObjectOutput serialize(URL url, OutputStream out) throws IOException { + return new FstObjectOutput(out); + } + + public ObjectInput deserialize(URL url, InputStream is) throws IOException { + return new FstObjectInput(is); + } +} \ No newline at end of file diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/json/JacksonObjectInput.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/json/JacksonObjectInput.java new file mode 100644 index 000000000000..f8a3c19ceec8 --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/json/JacksonObjectInput.java @@ -0,0 +1,178 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.serialize.support.json; + +import com.alibaba.dubbo.common.json.Jackson; +import com.alibaba.dubbo.common.serialize.ObjectInput; +import com.alibaba.dubbo.common.utils.ReflectUtils; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Type; +import java.util.Map; + +/** + * JsonObjectInput + * + * @author dylan + */ +public class JacksonObjectInput implements ObjectInput { + private static Logger logger = LoggerFactory.getLogger(JacksonObjectInput.class); + + private final ObjectMapper objectMapper; + // private final BufferedReader reader; + private final Map data; + private static final String KEY_PREFIX = "$"; + private int index = 0; + + public JacksonObjectInput(InputStream inputstream) throws IOException { +// this.reader = new BufferedReader(new InputStreamReader(inputstream)); +// String line = null; +// try { +// while ((line = reader.readLine()) != null) { +// System.out.println(line); +// } +// }catch(Exception e){ +// e.printStackTrace(); +// } + this.objectMapper = Jackson.getObjectMapper(); + try { + data = objectMapper.readValue(inputstream, Map.class); + } catch (IOException e) { + logger.error("parse inputstream error.", e); + throw e; + } + } + + public boolean readBool() throws IOException { + try { + return readObject(Boolean.class); + } catch (ClassNotFoundException e) { + throw new IOException(e.getMessage()); + } + } + + public byte readByte() throws IOException { + try { + return readObject(Byte.class); + } catch (ClassNotFoundException e) { + throw new IOException(e.getMessage()); + } + } + + public short readShort() throws IOException { + try { + return readObject(Short.class); + } catch (ClassNotFoundException e) { + throw new IOException(e.getMessage()); + } + } + + public int readInt() throws IOException { + try { + return readObject(Integer.class); + } catch (ClassNotFoundException e) { + throw new IOException(e.getMessage()); + } + } + + public long readLong() throws IOException { + try { + return readObject(Long.class); + } catch (ClassNotFoundException e) { + throw new IOException(e.getMessage()); + } + } + + public float readFloat() throws IOException { + try { + return readObject(Float.class); + } catch (ClassNotFoundException e) { + throw new IOException(e.getMessage()); + } + } + + public double readDouble() throws IOException { + try { + return readObject(Double.class); + } catch (ClassNotFoundException e) { + throw new IOException(e.getMessage()); + } + } + + public String readUTF() throws IOException { + try { + return readObject(String.class); + } catch (ClassNotFoundException e) { + throw new IOException(e.getMessage()); + } + } + + public byte[] readBytes() throws IOException { + return readUTF().getBytes(); + } + + public Object readObject() throws IOException, ClassNotFoundException { +// try { +// String json = readLine(); +// if (json.startsWith("{")) { +// return JSON.parse(json, Map.class); +// } else { +// json = "{\"value\":" + json + "}"; +// +// @SuppressWarnings("unchecked") +// Map map = objectMapper.readValue(json, Map.class); +// return map.get("value"); +// } +// } catch (ParseException e) { +// throw new IOException(e.getMessage()); +// } + try { + return readObject(Object.class); + } catch (ClassNotFoundException e) { + throw new IOException(e.getMessage()); + } + } + + @SuppressWarnings("unchecked") + public T readObject(Class cls) throws IOException, ClassNotFoundException { +// Object value = readObject(); + //read data value + String json = this.data.get(KEY_PREFIX + (++index)); + //read data type + String dataType = this.data.get(KEY_PREFIX + index + "t"); + if (dataType != null) { + Class clazz = ReflectUtils.desc2class(dataType); + if (cls.isAssignableFrom(clazz)) { + cls = clazz; + } else { + throw new IllegalArgumentException("Class \"" + clazz + "\" is not inherited from \"" + cls + "\""); + } + } + logger.debug("index:{}, value:{}", index, json); + return objectMapper.readValue(json, cls); + } + + @SuppressWarnings("unchecked") + public T readObject(Class cls, Type type) throws IOException, ClassNotFoundException { +// Object value = readObject(); + return readObject(cls); + } + +} \ No newline at end of file diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/json/JacksonObjectOutput.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/json/JacksonObjectOutput.java new file mode 100644 index 000000000000..b070c818c424 --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/json/JacksonObjectOutput.java @@ -0,0 +1,122 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.serialize.support.json; + +import com.alibaba.dubbo.common.json.Jackson; +import com.alibaba.dubbo.common.serialize.ObjectOutput; +import com.alibaba.dubbo.common.utils.ReflectUtils; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.*; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + * jackson object output + * + * @author dylan + */ +public class JacksonObjectOutput implements ObjectOutput { + + private final ObjectMapper objectMapper; + private final Map data; + private final static String KEY_PREFIX = "$"; + private int index = 0; + + private final PrintWriter writer; + + public JacksonObjectOutput(OutputStream out) { + this(new OutputStreamWriter(out)); + } + + public JacksonObjectOutput(Writer writer) { + this.objectMapper = Jackson.getObjectMapper(); + this.writer = new PrintWriter(writer); + this.data = new HashMap(); + } + + public void writeBool(boolean v) throws IOException { + writeObject0(v); + } + + public void writeByte(byte v) throws IOException { + writeObject0(v); + } + + public void writeShort(short v) throws IOException { + writeObject0(v); + } + + public void writeInt(int v) throws IOException { + writeObject0(v); + } + + public void writeLong(long v) throws IOException { + writeObject0(v); + } + + public void writeFloat(float v) throws IOException { + writeObject0(v); + } + + public void writeDouble(double v) throws IOException { + writeObject0(v); + } + + public void writeUTF(String v) throws IOException { + writeObject0(v); + } + + public void writeBytes(byte[] b) throws IOException { + writeObject0(new String(b)); + } + + public void writeBytes(byte[] b, int off, int len) throws IOException { + writeObject0(new String(b, off, len)); + } + + public void writeObject(Object obj) throws IOException { +// int i = ++index; + if (obj == null) { + writeObject0(obj); + return; + } + //write data value + writeObject0(obj); + //write data type + Class c = obj.getClass(); + String desc = ReflectUtils.getDesc(c); + data.put(KEY_PREFIX + (index) + "t", desc); +// if (obj instanceof Collection) { +// //集合类型 +// } else if (obj instanceof Map) { +// // +// } else { +// } + } + + private void writeObject0(Object obj) throws IOException { + data.put(KEY_PREFIX + (++index), objectMapper.writeValueAsString(obj)); + } + + public void flushBuffer() throws IOException { + objectMapper.writeValue(writer, data); + writer.println(); + writer.flush(); + } + +} \ No newline at end of file diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/json/JacksonSerialization.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/json/JacksonSerialization.java new file mode 100644 index 000000000000..2729cef5c3db --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/json/JacksonSerialization.java @@ -0,0 +1,50 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.serialize.support.json; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.serialize.ObjectInput; +import com.alibaba.dubbo.common.serialize.ObjectOutput; +import com.alibaba.dubbo.common.serialize.Serialization; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * JsonSerialization + * + * @author dylan + */ +public class JacksonSerialization implements Serialization { + + public byte getContentTypeId() { + return 20; + } + + public String getContentType() { + return "text/json"; + } + + public ObjectOutput serialize(URL url, OutputStream output) throws IOException { + return new JacksonObjectOutput(output); + } + + public ObjectInput deserialize(URL url, InputStream input) throws IOException { + return new JacksonObjectInput(input); + } + +} \ No newline at end of file diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/CompatibleKryo.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/CompatibleKryo.java new file mode 100644 index 000000000000..8ab2a9ecfdbf --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/CompatibleKryo.java @@ -0,0 +1,45 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.serialize.support.kryo; + +import com.alibaba.dubbo.common.logger.Logger; +import com.alibaba.dubbo.common.logger.LoggerFactory; +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.Serializer; +import com.esotericsoftware.kryo.serializers.JavaSerializer; + +/** + * @author lishen + */ +public class CompatibleKryo extends Kryo { + + private static final Logger logger = LoggerFactory.getLogger(CompatibleKryo.class); + + @Override + public Serializer getDefaultSerializer(Class type) { + if (type == null) { + throw new IllegalArgumentException("type cannot be null."); + } + + if (!type.isArray() && !ReflectionUtils.checkZeroArgConstructor(type)) { + if (logger.isWarnEnabled()) { + logger.warn(type + " has no zero-arg constructor and this will affect the serialization performance"); + } + return new JavaSerializer(); + } + return super.getDefaultSerializer(type); + } +} diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/KryoFactory.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/KryoFactory.java new file mode 100644 index 000000000000..a06efef1c457 --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/KryoFactory.java @@ -0,0 +1,142 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.serialize.support.kryo; + +import com.alibaba.dubbo.common.serialize.support.SerializableClassRegistry; +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.serializers.DefaultSerializers; +import de.javakaffee.kryoserializers.*; + +import java.lang.reflect.InvocationHandler; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.net.URI; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.regex.Pattern; + +/** + * @author lishen + */ +public abstract class KryoFactory { + +// private static final KryoFactory factory = new PrototypeKryoFactory(); +// private static final KryoFactory factory = new SingletonKryoFactory(); + private static final KryoFactory factory = new PooledKryoFactory(); + + private final Set registrations = new LinkedHashSet(); + + private boolean registrationRequired; + + private volatile boolean kryoCreated; + + protected KryoFactory() { + // TODO configurable +// Log.DEBUG(); + } + + public static KryoFactory getDefaultFactory() { + return factory; + } + + /** + * only supposed to be called at startup time + * + * later may consider adding support for custom serializer, custom id, etc + */ + public void registerClass(Class clazz) { + + if (kryoCreated) { + throw new IllegalStateException("Can't register class after creating kryo instance"); + } + registrations.add(clazz); + } + + protected Kryo createKryo() { + if (!kryoCreated) { + kryoCreated = true; + } + + Kryo kryo = new CompatibleKryo(); + + // TODO +// kryo.setReferences(false); + kryo.setRegistrationRequired(registrationRequired); + + kryo.register(Arrays.asList("").getClass(), new ArraysAsListSerializer()); + kryo.register(GregorianCalendar.class, new GregorianCalendarSerializer()); + kryo.register(InvocationHandler.class, new JdkProxySerializer()); + kryo.register(BigDecimal.class, new DefaultSerializers.BigDecimalSerializer()); + kryo.register(BigInteger.class, new DefaultSerializers.BigIntegerSerializer()); + kryo.register(Pattern.class, new RegexSerializer()); + kryo.register(BitSet.class, new BitSetSerializer()); + kryo.register(URI.class, new URISerializer()); + kryo.register(UUID.class, new UUIDSerializer()); + UnmodifiableCollectionsSerializer.registerSerializers(kryo); + SynchronizedCollectionsSerializer.registerSerializers(kryo); + + // now just added some very common classes + // TODO optimization + kryo.register(HashMap.class); + kryo.register(ArrayList.class); + kryo.register(LinkedList.class); + kryo.register(HashSet.class); + kryo.register(TreeSet.class); + kryo.register(Hashtable.class); + kryo.register(Date.class); + kryo.register(Calendar.class); + kryo.register(ConcurrentHashMap.class); + kryo.register(SimpleDateFormat.class); + kryo.register(GregorianCalendar.class); + kryo.register(Vector.class); + kryo.register(BitSet.class); + kryo.register(StringBuffer.class); + kryo.register(StringBuilder.class); + kryo.register(Object.class); + kryo.register(Object[].class); + kryo.register(String[].class); + kryo.register(byte[].class); + kryo.register(char[].class); + kryo.register(int[].class); + kryo.register(float[].class); + kryo.register(double[].class); + + for (Class clazz : registrations) { + kryo.register(clazz); + } + + for (Class clazz : SerializableClassRegistry.getRegisteredClasses()) { + kryo.register(clazz); + } + + return kryo; + } + + public void returnKryo(Kryo kryo) { + // do nothing by default + } + + public void setRegistrationRequired(boolean registrationRequired) { + this.registrationRequired = registrationRequired; + } + + public void close() { + // do nothing by default + } + + public abstract Kryo getKryo(); +} diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/KryoObjectInput.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/KryoObjectInput.java new file mode 100644 index 000000000000..e441a64c212a --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/KryoObjectInput.java @@ -0,0 +1,158 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.serialize.support.kryo; + +import com.alibaba.dubbo.common.serialize.Cleanable; +import com.alibaba.dubbo.common.serialize.ObjectInput; +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.KryoException; +import com.esotericsoftware.kryo.io.Input; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Type; + +/** + * @author lishen + */ +public class KryoObjectInput implements ObjectInput, Cleanable { + + private Kryo kryo = KryoFactory.getDefaultFactory().getKryo(); + private Input input; + + public KryoObjectInput(InputStream inputStream) { + input = new Input(inputStream); + } + + public boolean readBool() throws IOException { + try { + return input.readBoolean(); + } catch (KryoException e) { + throw new IOException(e); + } + } + + public byte readByte() throws IOException { + try { + return input.readByte(); + } catch (KryoException e) { + throw new IOException(e); + } + } + + public short readShort() throws IOException { + try { + return input.readShort(); + } catch (KryoException e) { + throw new IOException(e); + } + } + + public int readInt() throws IOException { + try { + return input.readInt(); + } catch (KryoException e) { + throw new IOException(e); + } + } + + public long readLong() throws IOException { + try { + return input.readLong(); + } catch (KryoException e) { + throw new IOException(e); + } + } + + public float readFloat() throws IOException { + try { + return input.readFloat(); + } catch (KryoException e) { + throw new IOException(e); + } + } + + public double readDouble() throws IOException { + try { + return input.readDouble(); + } catch (KryoException e) { + throw new IOException(e); + } + } + + public byte[] readBytes() throws IOException { + try { + int len = input.readInt(); + if (len < 0) { + return null; + } else if (len == 0) { + return new byte[]{}; + } else { + return input.readBytes(len); + } + } catch (KryoException e) { + throw new IOException(e); + } + } + + public String readUTF() throws IOException { + // TODO + try { +// return kryo.readObject(input, String.class); + return input.readString(); + } catch (KryoException e) { + throw new IOException(e); + } + } + + public Object readObject() throws IOException, ClassNotFoundException { + // TODO +// throw new UnsupportedOperationException(); + try { + return kryo.readClassAndObject(input); + } catch (KryoException e) { + throw new IOException(e); + } + } + + + @SuppressWarnings("unchecked") + public T readObject(Class clazz) throws IOException, ClassNotFoundException { + // TODO optimization +// try { +// return (T) kryo.readClassAndObject(input); +// } catch (KryoException e) { +// throw new IOException(e); +// } + return (T) readObject(); + } + + @SuppressWarnings("unchecked") + public T readObject(Class clazz, Type type) throws IOException, ClassNotFoundException { +// try { +// return readObject(clazz); +// } catch (KryoException e) { +// throw new IOException(e); +// } + // TODO optimization + return (T) readObject(clazz); + } + + public void cleanup() { + KryoFactory.getDefaultFactory().returnKryo(kryo); + kryo = null; + } +} \ No newline at end of file diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/KryoObjectOutput.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/KryoObjectOutput.java new file mode 100644 index 000000000000..fb127be60200 --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/KryoObjectOutput.java @@ -0,0 +1,102 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.serialize.support.kryo; + +import com.alibaba.dubbo.common.serialize.Cleanable; +import com.alibaba.dubbo.common.serialize.ObjectOutput; +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.io.Output; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * @author lishen + */ +public class KryoObjectOutput implements ObjectOutput, Cleanable { + + private Kryo kryo = KryoFactory.getDefaultFactory().getKryo(); + private Output output; + + public KryoObjectOutput(OutputStream outputStream) { + output = new Output(outputStream); + } + + public void writeBool(boolean v) throws IOException { + output.writeBoolean(v); + } + + public void writeByte(byte v) throws IOException { + output.writeByte(v); + } + + public void writeShort(short v) throws IOException { + output.writeShort(v); + } + + public void writeInt(int v) throws IOException { + output.writeInt(v); + } + + public void writeLong(long v) throws IOException { + output.writeLong(v); + } + + public void writeFloat(float v) throws IOException { + output.writeFloat(v); + } + + public void writeDouble(double v) throws IOException { + output.writeDouble(v); + } + + public void writeBytes(byte[] v) throws IOException { + if (v == null) { + output.writeInt(-1); + } else { + writeBytes(v, 0, v.length); + } + } + + public void writeBytes(byte[] v, int off, int len) throws IOException { + if (v == null) { + output.writeInt(-1); + } else { + output.writeInt(len); + output.write(v, off, len); + } + } + + + public void writeUTF(String v) throws IOException { + // TODO + output.writeString(v); +// kryo.writeObject(output, v); + } + + public void writeObject(Object v) throws IOException { + kryo.writeClassAndObject(output, v); + } + + public void flushBuffer() throws IOException { + output.flush(); + } + + public void cleanup() { + KryoFactory.getDefaultFactory().returnKryo(kryo); + kryo = null; + } +} \ No newline at end of file diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/KryoSerialization.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/KryoSerialization.java new file mode 100644 index 000000000000..07766cb4c5f1 --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/KryoSerialization.java @@ -0,0 +1,49 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.serialize.support.kryo; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.serialize.ObjectInput; +import com.alibaba.dubbo.common.serialize.ObjectOutput; +import com.alibaba.dubbo.common.serialize.OptimizedSerialization; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * TODO for now kryo serialization doesn't deny classes that don't implement the serializable interface + * + * @author lishen + */ +public class KryoSerialization implements OptimizedSerialization { + + public byte getContentTypeId() { + return 8; + } + + public String getContentType() { + return "x-application/kryo"; + } + + public ObjectOutput serialize(URL url, OutputStream out) throws IOException { + return new KryoObjectOutput(out); + } + + public ObjectInput deserialize(URL url, InputStream is) throws IOException { + return new KryoObjectInput(is); + } +} \ No newline at end of file diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/PooledKryoFactory.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/PooledKryoFactory.java new file mode 100644 index 000000000000..7c2cfa5a6aa0 --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/PooledKryoFactory.java @@ -0,0 +1,47 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.serialize.support.kryo; + +import com.esotericsoftware.kryo.Kryo; + +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + +/** + * @author lishen + */ +public class PooledKryoFactory extends KryoFactory { + + private final Queue pool = new ConcurrentLinkedQueue(); + + @Override + public void returnKryo(Kryo kryo) { + pool.offer(kryo); + } + + @Override + public void close() { + pool.clear(); + } + + public Kryo getKryo() { + Kryo kryo = pool.poll(); + if (kryo == null) { + kryo = createKryo(); + } + return kryo; + } +} diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/PrototypeKryoFactory.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/PrototypeKryoFactory.java new file mode 100644 index 000000000000..06c18787cbbf --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/PrototypeKryoFactory.java @@ -0,0 +1,28 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.serialize.support.kryo; + +import com.esotericsoftware.kryo.Kryo; + +/** + * @author lishen + */ +public class PrototypeKryoFactory extends KryoFactory { + + public Kryo getKryo() { + return createKryo(); + } +} diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/ReflectionUtils.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/ReflectionUtils.java new file mode 100644 index 000000000000..40997fe39988 --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/ReflectionUtils.java @@ -0,0 +1,31 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.serialize.support.kryo; + +/** + * @author lishen + */ +public abstract class ReflectionUtils { + + public static boolean checkZeroArgConstructor(Class clazz) { + try { + clazz.getDeclaredConstructor(); + return true; + } catch (NoSuchMethodException e) { + return false; + } + } +} diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/SingletonKryoFactory.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/SingletonKryoFactory.java new file mode 100644 index 000000000000..2e3aefd487e4 --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/SingletonKryoFactory.java @@ -0,0 +1,37 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.serialize.support.kryo; + +import com.esotericsoftware.kryo.Kryo; + +/** + * CAUSION this is only for test purpose since both kryo and this class are not thread-safe + * + * @author lishen + */ +public class SingletonKryoFactory extends KryoFactory { + +// private final Kryo instance = createKryo(); + private Kryo instance; + + @Override + public Kryo getKryo() { + if (instance == null) { + instance = createKryo(); + } + return instance; + } +} diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/ThreadLocalKryoFactory.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/ThreadLocalKryoFactory.java new file mode 100644 index 000000000000..aee8659ab5d6 --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/serialize/support/kryo/ThreadLocalKryoFactory.java @@ -0,0 +1,35 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.serialize.support.kryo; + +import com.esotericsoftware.kryo.Kryo; + +/** + * @author lishen + */ +public class ThreadLocalKryoFactory extends KryoFactory { + + private final ThreadLocal holder = new ThreadLocal() { + @Override + protected Kryo initialValue() { + return createKryo(); + } + }; + + public Kryo getKryo() { + return holder.get(); + } +} diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/ExecutorUtil.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/ExecutorUtil.java index 0de8305a5995..d4f336abfb1e 100644 --- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/ExecutorUtil.java +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/ExecutorUtil.java @@ -1,18 +1,18 @@ -/* - * Copyright 1999-2011 Alibaba Group. - * - * Licensed 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. - */ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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 java.util.concurrent.Executor; @@ -21,6 +21,8 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import com.alibaba.dubbo.common.Constants; +import com.alibaba.dubbo.common.URL; import com.alibaba.dubbo.common.logger.Logger; import com.alibaba.dubbo.common.logger.LoggerFactory; @@ -93,20 +95,31 @@ private static void newThreadToCloseExecutor(final ExecutorService es) { if (!isShutdown(es)) { shutdownExecutor.execute(new Runnable() { public void run() { - try { + try { for (int i=0;i<1000;i++){ - es.shutdownNow(); - if (es.awaitTermination(10, TimeUnit.MILLISECONDS)){ - break; - } + es.shutdownNow(); + if (es.awaitTermination(10, TimeUnit.MILLISECONDS)){ + break; + } } - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } catch (Throwable e) { - logger.warn(e.getMessage(), e); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } catch (Throwable e) { + logger.warn(e.getMessage(), e); } } }); } } + + /** + * append thread name with url address + * @return new url with updated thread name + */ + public static URL setThreadName(URL url, String defaultName) { + String name = url.getParameter(Constants.THREAD_NAME_KEY, defaultName); + name = new StringBuilder(32).append(name).append("-").append(url.getAddress()).toString(); + url = url.addParameter(Constants.THREAD_NAME_KEY, name); + return url; + } } \ No newline at end of file diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/LogHelper.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/LogHelper.java new file mode 100644 index 000000000000..92a51c977454 --- /dev/null +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/LogHelper.java @@ -0,0 +1,179 @@ +/* + * Copyright 1999-2012 Alibaba Group. + * + * Licensed 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.logger.Logger; + +/** + * @author kimi + */ +public class LogHelper { + + public static void trace(Logger logger, String msg) { + if (logger == null) { + return; + } + + if (logger.isTraceEnabled()) { + logger.trace(msg); + } + } + + public static void trace(Logger logger, Throwable throwable) { + if (logger == null) { + return; + } + + if (logger.isTraceEnabled()) { + logger.trace(throwable); + } + } + + public static void trace(Logger logger, String msg, Throwable e) { + if (logger == null) { + return; + } + + if (logger.isTraceEnabled()) { + logger.trace(msg, e); + } + } + + public static void debug(Logger logger, String msg) { + if (logger == null) { + return; + } + + if (logger.isDebugEnabled()) { + logger.debug(msg); + } + } + + public static void debug(Logger logger, Throwable e) { + if (logger == null) { + return; + } + + if (logger.isDebugEnabled()) { + logger.debug(e); + } + } + + public static void debug(Logger logger, String msg, Throwable e) { + if (logger == null) { + return; + } + + if (logger.isDebugEnabled()) { + logger.debug(msg, e); + } + } + + public static void info(Logger logger, String msg) { + if (logger == null) { + return; + } + + if (logger.isInfoEnabled()) { + logger.info(msg); + } + } + + public static void info(Logger logger, Throwable e) { + if (logger == null) { + return; + } + + if (logger.isInfoEnabled()) { + logger.info(e); + } + } + + public static void info(Logger logger, String msg, Throwable e) { + if (logger == null) { + return; + } + + if (logger.isInfoEnabled()) { + logger.info(msg, e); + } + } + + public static void warn(Logger logger, String msg, Throwable e) { + if (logger == null) { + return; + } + + if (logger.isWarnEnabled()) { + logger.warn(msg, e); + } + } + + public static void warn(Logger logger, String msg) { + if (logger == null) { + return; + } + + if (logger.isWarnEnabled()) { + logger.warn(msg); + } + } + + public static void warn(Logger logger, Throwable e) { + if (logger == null) { + return; + } + + if (logger.isWarnEnabled()) { + logger.warn(e); + } + } + + public static void error(Logger logger, Throwable e) { + if (logger == null) { + return; + } + + if (logger.isErrorEnabled()) { + logger.error(e); + } + } + + public static void error(Logger logger, String msg) { + if (logger == null) { + return; + } + + if (logger.isErrorEnabled()) { + logger.error(msg); + } + } + + public static void error(Logger logger, String msg, Throwable e) { + if (logger == null) { + return; + } + + if (logger.isErrorEnabled()) { + logger.error(msg, e); + } + } + + private LogHelper() { + } + +} diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/ReflectUtils.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/ReflectUtils.java index 93fc00826fe1..ccd6aa7b9653 100644 --- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/ReflectUtils.java +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/ReflectUtils.java @@ -945,7 +945,8 @@ public static boolean isBeanPropertyReadMethod(Method method) { && method.getReturnType() != void.class && method.getDeclaringClass() != Object.class && method.getParameterTypes().length == 0 - && (method.getName().startsWith("get") || method.getName().startsWith("is")); + && ((method.getName().startsWith("get") && method.getName().length() > 3) + || (method.getName().startsWith("is") && method.getName().length() > 2)); } public static String getPropertyNameFromBeanReadMethod(Method method) { @@ -968,7 +969,8 @@ public static boolean isBeanPropertyWriteMethod(Method method) { && ! Modifier.isStatic(method.getModifiers()) && method.getDeclaringClass() != Object.class && method.getParameterTypes().length == 1 - && method.getName().startsWith("set"); + && method.getName().startsWith("set") + && method.getName().length() > 3; } public static String getPropertyNameFromBeanWriteMethod(Method method) { @@ -986,5 +988,40 @@ public static boolean isPublicInstanceField(Field field) { && !field.isSynthetic(); } + public static Map getBeanPropertyFields(Class cl) { + Map properties = new HashMap(); + for(; cl != null; cl = cl.getSuperclass()) { + Field[] fields = cl.getDeclaredFields(); + for(Field field : fields) { + if (Modifier.isTransient(field.getModifiers()) + || Modifier.isStatic(field.getModifiers())) { + continue; + } + + field.setAccessible(true); + + properties.put(field.getName(), field); + } + } + + return properties; + } + + public static Map getBeanPropertyReadMethods(Class cl) { + Map properties = new HashMap(); + for(; cl != null; cl = cl.getSuperclass()) { + Method[] methods = cl.getDeclaredMethods(); + for(Method method : methods) { + if (isBeanPropertyReadMethod(method)) { + method.setAccessible(true); + String property = getPropertyNameFromBeanReadMethod(method); + properties.put(property, method); + } + } + } + + return properties; + } + private ReflectUtils(){} } \ No newline at end of file diff --git a/dubbo-common/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.common.json.JacksonObjectMapperProvider b/dubbo-common/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.common.json.JacksonObjectMapperProvider new file mode 100644 index 000000000000..73e8cf261f55 --- /dev/null +++ b/dubbo-common/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.common.json.JacksonObjectMapperProvider @@ -0,0 +1 @@ +jackson=com.alibaba.dubbo.common.json.DefaultJacksonObjectMapperProvider \ No newline at end of file diff --git a/dubbo-common/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.common.serialize.Serialization b/dubbo-common/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.common.serialize.Serialization index ca493e457992..2362c9acb886 100644 --- a/dubbo-common/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.common.serialize.Serialization +++ b/dubbo-common/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.common.serialize.Serialization @@ -4,4 +4,7 @@ java=com.alibaba.dubbo.common.serialize.support.java.JavaSerialization compactedjava=com.alibaba.dubbo.common.serialize.support.java.CompactedJavaSerialization json=com.alibaba.dubbo.common.serialize.support.json.JsonSerialization fastjson=com.alibaba.dubbo.common.serialize.support.json.FastJsonSerialization -nativejava=com.alibaba.dubbo.common.serialize.support.nativejava.NativeJavaSerialization \ No newline at end of file +nativejava=com.alibaba.dubbo.common.serialize.support.nativejava.NativeJavaSerialization +kryo=com.alibaba.dubbo.common.serialize.support.kryo.KryoSerialization +fst=com.alibaba.dubbo.common.serialize.support.fst.FstSerialization +jackson=com.alibaba.dubbo.common.serialize.support.json.JacksonSerialization \ No newline at end of file diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/beanutil/Bean.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/beanutil/Bean.java new file mode 100644 index 000000000000..acc896b3394e --- /dev/null +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/beanutil/Bean.java @@ -0,0 +1,75 @@ +package com.alibaba.dubbo.common.beanutil; + +import java.util.Collection; +import java.util.Date; +import java.util.Map; + +import com.alibaba.dubbo.common.model.person.FullAddress; +import com.alibaba.dubbo.common.model.person.PersonStatus; +import com.alibaba.dubbo.common.model.person.Phone; + +/** + * @author kimi + */ +public class Bean { + + private Class type; + + private PersonStatus status; + + private Date date; + + private Phone[] array; + + private Collection collection; + + private Map addresses; + + public Class getType() { + return type; + } + + public void setType(Class type) { + this.type = type; + } + + public PersonStatus getStatus() { + return status; + } + + public void setStatus(PersonStatus status) { + this.status = status; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public Phone[] getArray() { + return array; + } + + public void setArray(Phone[] array) { + this.array = array; + } + + public Collection getCollection() { + return collection; + } + + public void setCollection(Collection collection) { + this.collection = collection; + } + + public Map getAddresses() { + return addresses; + } + + public void setAddresses(Map addresses) { + this.addresses = addresses; + } +} diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/beanutil/JavaBeanSerializeUtilTest.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/beanutil/JavaBeanSerializeUtilTest.java new file mode 100644 index 000000000000..99557e502a16 --- /dev/null +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/beanutil/JavaBeanSerializeUtilTest.java @@ -0,0 +1,412 @@ +/* + * Copyright 1999-2012 Alibaba Group. + * + * Licensed 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.beanutil; + +import java.lang.reflect.Array; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.junit.Test; + +import org.junit.Assert; + +import com.alibaba.dubbo.common.model.person.BigPerson; +import com.alibaba.dubbo.common.model.person.FullAddress; +import com.alibaba.dubbo.common.model.person.PersonInfo; +import com.alibaba.dubbo.common.model.person.PersonStatus; +import com.alibaba.dubbo.common.model.person.Phone; +import com.alibaba.dubbo.common.utils.PojoUtilsTest; + +/** + * @author kimi + */ +public class JavaBeanSerializeUtilTest { + + @Test + public void testSerialize_Primitive() throws Exception { + JavaBeanDescriptor descriptor; + descriptor = JavaBeanSerializeUtil.serialize(Integer.MAX_VALUE); + Assert.assertTrue(descriptor.isPrimitiveType()); + Assert.assertEquals(Integer.MAX_VALUE, descriptor.getPrimitiveProperty()); + + Date now = new Date(); + descriptor = JavaBeanSerializeUtil.serialize(now); + Assert.assertTrue(descriptor.isPrimitiveType()); + Assert.assertEquals(now, descriptor.getPrimitiveProperty()); + } + + @Test + public void testDeserialize_Primitive() throws Exception { + JavaBeanDescriptor descriptor = new JavaBeanDescriptor(long.class.getName(), JavaBeanDescriptor.TYPE_PRIMITIVE); + descriptor.setPrimitiveProperty(Long.MAX_VALUE); + Assert.assertEquals(Long.MAX_VALUE, JavaBeanSerializeUtil.deserialize(descriptor)); + + BigDecimal decimal = BigDecimal.TEN; + Assert.assertEquals(Long.MAX_VALUE, descriptor.setPrimitiveProperty(decimal)); + Assert.assertEquals(decimal, JavaBeanSerializeUtil.deserialize(descriptor)); + + String string = UUID.randomUUID().toString(); + Assert.assertEquals(decimal, descriptor.setPrimitiveProperty(string)); + Assert.assertEquals(string, JavaBeanSerializeUtil.deserialize(descriptor)); + } + + @Test + public void testSerialize_Array() throws Exception { + int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + JavaBeanDescriptor descriptor = JavaBeanSerializeUtil.serialize(array, JavaBeanAccessor.METHOD); + Assert.assertTrue(descriptor.isArrayType()); + Assert.assertEquals(int.class.getName(), descriptor.getClassName()); + for (int i = 0; i < array.length; i++) { + Assert.assertEquals(array[i], + ((JavaBeanDescriptor) descriptor.getProperty(i)).getPrimitiveProperty()); + } + + Integer[] integers = new Integer[]{1, 2, 3, 4, null, null, null}; + descriptor = JavaBeanSerializeUtil.serialize(integers, JavaBeanAccessor.METHOD); + Assert.assertTrue(descriptor.isArrayType()); + Assert.assertEquals(Integer.class.getName(), descriptor.getClassName()); + Assert.assertEquals(integers.length, descriptor.propertySize()); + for(int i = 0; i < integers.length; i++) { + if (integers[i] == null) { + Assert.assertTrue(integers[i] == descriptor.getProperty(i)); + } else { + Assert.assertEquals(integers[i], ((JavaBeanDescriptor)descriptor.getProperty(i)).getPrimitiveProperty()); + } + } + + int[][] second = {{1, 2}, {3, 4}}; + descriptor = JavaBeanSerializeUtil.serialize(second, JavaBeanAccessor.METHOD); + Assert.assertTrue(descriptor.isArrayType()); + Assert.assertEquals(int[].class.getName(), descriptor.getClassName()); + for(int i = 0; i < second.length; i++) { + for(int j = 0; j < second[i].length; j++) { + JavaBeanDescriptor item = (((JavaBeanDescriptor)descriptor.getProperty(i))); + Assert.assertTrue(item.isArrayType()); + Assert.assertEquals(int.class.getName(), item.getClassName()); + Assert.assertEquals(second[i][j], ((JavaBeanDescriptor)item.getProperty(j)).getPrimitiveProperty()); + } + } + + BigPerson[] persons = new BigPerson[] {createBigPerson(), createBigPerson()}; + descriptor = JavaBeanSerializeUtil.serialize(persons); + Assert.assertTrue(descriptor.isArrayType()); + Assert.assertEquals(BigPerson.class.getName(), descriptor.getClassName()); + for(int i = 0; i < persons.length; i++) { + assertEqualsBigPerson(persons[i], descriptor.getProperty(i)); + } + } + + @Test + public void testDeserialize_Array() throws Exception { + final int len = 10; + JavaBeanDescriptor descriptor = new JavaBeanDescriptor(int.class.getName(), JavaBeanDescriptor.TYPE_ARRAY); + for(int i = 0; i < len; i++) { + descriptor.setProperty(i, i); + } + + Object obj = JavaBeanSerializeUtil.deserialize(descriptor); + Assert.assertTrue(obj.getClass().isArray()); + Assert.assertTrue(int.class == obj.getClass().getComponentType()); + for(int i = 0; i < len; i++) { + Assert.assertEquals(i, Array.get(obj, i)); + } + + descriptor = new JavaBeanDescriptor(int[].class.getName(), JavaBeanDescriptor.TYPE_ARRAY); + for(int i = 0; i < len; i++) { + JavaBeanDescriptor innerItem = new JavaBeanDescriptor(int.class.getName(), JavaBeanDescriptor.TYPE_ARRAY); + for (int j = 0; j < len; j++) { + innerItem.setProperty(j, j); + } + descriptor.setProperty(i, innerItem); + } + obj = JavaBeanSerializeUtil.deserialize(descriptor); + Assert.assertTrue(obj.getClass().isArray()); + Assert.assertEquals(int[].class, obj.getClass().getComponentType()); + for(int i = 0; i < len; i++) { + Object innerItem = Array.get(obj, i); + Assert.assertTrue(innerItem.getClass().isArray()); + Assert.assertEquals(int.class, innerItem.getClass().getComponentType()); + for (int j = 0; j < len; j++) { + Assert.assertEquals(j, Array.get(innerItem, j)); + } + } + + descriptor = new JavaBeanDescriptor(BigPerson[].class.getName(), JavaBeanDescriptor.TYPE_ARRAY); + JavaBeanDescriptor innerDescriptor = new JavaBeanDescriptor(BigPerson.class.getName(), JavaBeanDescriptor.TYPE_ARRAY); + innerDescriptor.setProperty(0, JavaBeanSerializeUtil.serialize(createBigPerson(), JavaBeanAccessor.METHOD)); + descriptor.setProperty(0, innerDescriptor); + + obj = JavaBeanSerializeUtil.deserialize(descriptor); + Assert.assertTrue(obj.getClass().isArray()); + Assert.assertEquals(BigPerson[].class, obj.getClass().getComponentType()); + Assert.assertEquals(1, Array.getLength(obj)); + obj = Array.get(obj, 0); + Assert.assertTrue(obj.getClass().isArray()); + Assert.assertEquals(BigPerson.class, obj.getClass().getComponentType()); + Assert.assertEquals(1, Array.getLength(obj)); + Assert.assertEquals(createBigPerson(), Array.get(obj, 0)); + } + + @Test + public void test_Circular_Reference() throws Exception { + PojoUtilsTest.Parent parent = new PojoUtilsTest.Parent(); + parent.setAge(Integer.MAX_VALUE); + parent.setEmail("a@b"); + parent.setName("zhangsan"); + + PojoUtilsTest.Child child = new PojoUtilsTest.Child(); + child.setAge(100); + child.setName("lisi"); + child.setParent(parent); + + parent.setChild(child); + + JavaBeanDescriptor descriptor = JavaBeanSerializeUtil.serialize(parent, JavaBeanAccessor.METHOD); + Assert.assertTrue(descriptor.isBeanType()); + assertEqualsPrimitive(parent.getAge(), descriptor.getProperty("age")); + assertEqualsPrimitive(parent.getName(), descriptor.getProperty("name")); + assertEqualsPrimitive(parent.getEmail(), descriptor.getProperty("email")); + + JavaBeanDescriptor childDescriptor = (JavaBeanDescriptor) descriptor.getProperty("child"); + Assert.assertTrue(descriptor == childDescriptor.getProperty("parent")); + assertEqualsPrimitive(child.getName(), childDescriptor.getProperty("name")); + assertEqualsPrimitive(child.getAge(), childDescriptor.getProperty("age")); + } + + @Test + public void testBeanSerialize() throws Exception { + Bean bean = new Bean(); + bean.setDate(new Date()); + bean.setStatus(PersonStatus.ENABLED); + bean.setType(Bean.class); + bean.setArray(new Phone[]{}); + + Collection collection = new ArrayList(); + bean.setCollection(collection); + Phone phone = new Phone(); + collection.add(phone); + + Map map = new HashMap(); + FullAddress address = new FullAddress(); + map.put("first", address); + bean.setAddresses(map); + + JavaBeanDescriptor descriptor = JavaBeanSerializeUtil.serialize(bean, JavaBeanAccessor.METHOD); + Assert.assertTrue(descriptor.isBeanType()); + assertEqualsPrimitive(bean.getDate(), descriptor.getProperty("date")); + assertEqualsEnum(bean.getStatus(), descriptor.getProperty("status")); + Assert.assertTrue(((JavaBeanDescriptor)descriptor.getProperty("type")).isClassType()); + Assert.assertEquals(Bean.class.getName(), ((JavaBeanDescriptor)descriptor.getProperty("type")).getClassNameProperty()); + Assert.assertTrue(((JavaBeanDescriptor)descriptor.getProperty("array")).isArrayType()); + Assert.assertEquals(0, ((JavaBeanDescriptor)descriptor.getProperty("array")).propertySize()); + + JavaBeanDescriptor property = (JavaBeanDescriptor)descriptor.getProperty("collection"); + Assert.assertTrue(property.isCollectionType()); + Assert.assertEquals(1, property.propertySize()); + property = (JavaBeanDescriptor)property.getProperty(0); + Assert.assertTrue(property.isBeanType()); + Assert.assertEquals(Phone.class.getName(), property.getClassName()); + Assert.assertEquals(0, property.propertySize()); + + property = (JavaBeanDescriptor)descriptor.getProperty("addresses"); + Assert.assertTrue(property.isMapType()); + Assert.assertEquals(bean.getAddresses().getClass().getName(), property.getClassName()); + Assert.assertEquals(1, property.propertySize()); + + + Map.Entry entry = property.iterator().next(); + Assert.assertTrue(((JavaBeanDescriptor)entry.getKey()).isPrimitiveType()); + Assert.assertEquals("first", ((JavaBeanDescriptor)entry.getKey()).getPrimitiveProperty()); + + Assert.assertTrue(((JavaBeanDescriptor)entry.getValue()).isBeanType()); + Assert.assertEquals(FullAddress.class.getName(), ((JavaBeanDescriptor)entry.getValue()).getClassName()); + Assert.assertEquals(0, ((JavaBeanDescriptor)entry.getValue()).propertySize()); + } + + @Test + public void testDeserializeBean() throws Exception { + Bean bean = new Bean(); + bean.setDate(new Date()); + bean.setStatus(PersonStatus.ENABLED); + bean.setType(Bean.class); + bean.setArray(new Phone[]{}); + + Collection collection = new ArrayList(); + bean.setCollection(collection); + Phone phone = new Phone(); + collection.add(phone); + + Map map = new HashMap(); + FullAddress address = new FullAddress(); + map.put("first", address); + bean.setAddresses(map); + + JavaBeanDescriptor beanDescriptor = JavaBeanSerializeUtil.serialize(bean, JavaBeanAccessor.METHOD); + Object deser = JavaBeanSerializeUtil.deserialize(beanDescriptor); + Assert.assertTrue(deser instanceof Bean); + Bean deserBean = (Bean)deser; + Assert.assertEquals(bean.getDate(), deserBean.getDate()); + Assert.assertEquals(bean.getStatus(), deserBean.getStatus()); + Assert.assertEquals(bean.getType(), deserBean.getType()); + Assert.assertEquals(bean.getCollection().size(), deserBean.getCollection().size()); + Assert.assertEquals(bean.getCollection().iterator().next().getClass(), + deserBean.getCollection().iterator().next().getClass()); + Assert.assertEquals(bean.getAddresses().size(), deserBean.getAddresses().size()); + Assert.assertEquals(bean.getAddresses().entrySet().iterator().next().getKey(), + deserBean.getAddresses().entrySet().iterator().next().getKey()); + Assert.assertEquals(bean.getAddresses().entrySet().iterator().next().getValue().getClass(), + deserBean.getAddresses().entrySet().iterator().next().getValue().getClass()); + } + + @Test + @SuppressWarnings("unchecked") + public void testSerializeJavaBeanDescriptor() throws Exception { + JavaBeanDescriptor descriptor = new JavaBeanDescriptor(); + JavaBeanDescriptor result = JavaBeanSerializeUtil.serialize(descriptor); + Assert.assertTrue(descriptor == result); + + Map map = new HashMap(); + map.put("first", descriptor); + result = JavaBeanSerializeUtil.serialize(map); + Assert.assertTrue(result.isMapType()); + Assert.assertEquals(HashMap.class.getName(), result.getClassName()); + Assert.assertEquals(map.size(), result.propertySize()); + Object object = result.iterator().next().getValue(); + Assert.assertTrue(object instanceof JavaBeanDescriptor); + JavaBeanDescriptor actual = (JavaBeanDescriptor)object; + Assert.assertEquals(map.get("first"), actual); + } + + static void assertEqualsEnum(Enum expected, Object obj) { + JavaBeanDescriptor descriptor = (JavaBeanDescriptor) obj; + Assert.assertTrue(descriptor.isEnumType()); + Assert.assertEquals(expected.getClass().getName(), descriptor.getClassName()); + Assert.assertEquals(expected.name(), descriptor.getEnumPropertyName()); + } + + static void assertEqualsPrimitive(Object expected, Object obj) { + if (expected == null) { return; } + JavaBeanDescriptor descriptor = (JavaBeanDescriptor) obj; + Assert.assertTrue(descriptor.isPrimitiveType()); + Assert.assertEquals(expected, descriptor.getPrimitiveProperty()); + } + + static void assertEqualsBigPerson(BigPerson person, Object obj) { + JavaBeanDescriptor descriptor = (JavaBeanDescriptor)obj; + Assert.assertTrue(descriptor.isBeanType()); + assertEqualsPrimitive(person.getPersonId(), descriptor.getProperty("personId")); + assertEqualsPrimitive(person.getLoginName(), descriptor.getProperty("loginName")); + assertEqualsEnum(person.getStatus(), descriptor.getProperty("status")); + assertEqualsPrimitive(person.getEmail(), descriptor.getProperty("email")); + assertEqualsPrimitive(person.getPenName(), descriptor.getProperty("penName")); + + JavaBeanDescriptor infoProfile = (JavaBeanDescriptor)descriptor.getProperty("infoProfile"); + Assert.assertTrue(infoProfile.isBeanType()); + JavaBeanDescriptor phones = (JavaBeanDescriptor) infoProfile.getProperty("phones"); + Assert.assertTrue(phones.isCollectionType()); + assertEqualsPhone(person.getInfoProfile().getPhones().get(0), phones.getProperty(0)); + assertEqualsPhone(person.getInfoProfile().getPhones().get(1), phones.getProperty(1)); + assertEqualsPhone(person.getInfoProfile().getFax(), infoProfile.getProperty("fax")); + assertEqualsFullAddress(person.getInfoProfile().getFullAddress(), infoProfile.getProperty("fullAddress")); + assertEqualsPrimitive(person.getInfoProfile().getMobileNo(), infoProfile.getProperty("mobileNo")); + assertEqualsPrimitive(person.getInfoProfile().getName(), infoProfile.getProperty("name")); + assertEqualsPrimitive(person.getInfoProfile().getDepartment(), infoProfile.getProperty("department")); + assertEqualsPrimitive(person.getInfoProfile().getJobTitle(), infoProfile.getProperty("jobTitle")); + assertEqualsPrimitive(person.getInfoProfile().getHomepageUrl(), infoProfile.getProperty("homepageUrl")); + assertEqualsPrimitive(person.getInfoProfile().isFemale(), infoProfile.getProperty("female")); + assertEqualsPrimitive(person.getInfoProfile().isMale(), infoProfile.getProperty("male")); + } + + static void assertEqualsPhone(Phone excpected, Object obj) { + JavaBeanDescriptor descriptor = (JavaBeanDescriptor)obj; + Assert.assertTrue(descriptor.isBeanType()); + if (excpected.getArea() != null) { + assertEqualsPrimitive(excpected.getArea(), descriptor.getProperty("area")); + } + if (excpected.getCountry() != null) { + assertEqualsPrimitive(excpected.getCountry(), descriptor.getProperty("country")); + } + if (excpected.getExtensionNumber()!= null) { + assertEqualsPrimitive(excpected.getExtensionNumber(), descriptor.getProperty("extensionNumber")); + } + if (excpected.getNumber() != null) { + assertEqualsPrimitive(excpected.getNumber(), descriptor.getProperty("number")); + } + } + + static void assertEqualsFullAddress(FullAddress expected, Object obj) { + JavaBeanDescriptor descriptor = (JavaBeanDescriptor)obj; + Assert.assertTrue(descriptor.isBeanType()); + if (expected.getCityId() != null) { + assertEqualsPrimitive(expected.getCityId(), descriptor.getProperty("cityId")); + } + if (expected.getCityName() != null) { + assertEqualsPrimitive(expected.getCityName(), descriptor.getProperty("cityName")); + } + if (expected.getCountryId() != null) { + assertEqualsPrimitive(expected.getCountryId(), descriptor.getProperty("countryId")); + } + if (expected.getCountryName() != null) { + assertEqualsPrimitive(expected.getCountryName(), descriptor.getProperty("countryName")); + } + if (expected.getProvinceName() != null) { + assertEqualsPrimitive(expected.getProvinceName(), descriptor.getProperty("provinceName")); + } + if (expected.getStreetAddress() != null) { + assertEqualsPrimitive(expected.getStreetAddress(), descriptor.getProperty("streetAddress")); + } + if (expected.getZipCode() != null) { + assertEqualsPrimitive(expected.getZipCode(), descriptor.getProperty("zipCode")); + } + } + + static BigPerson createBigPerson() { + BigPerson bigPerson; + bigPerson = new BigPerson(); + bigPerson.setPersonId("superman111"); + bigPerson.setLoginName("superman"); + bigPerson.setStatus(PersonStatus.ENABLED); + bigPerson.setEmail("sm@1.com"); + bigPerson.setPenName("pname"); + + ArrayList phones = new ArrayList(); + Phone phone1 = new Phone("86", "0571", "87654321", "001"); + Phone phone2 = new Phone("86", "0571", "87654322", "002"); + phones.add(phone1); + phones.add(phone2); + + PersonInfo pi = new PersonInfo(); + pi.setPhones(phones); + Phone fax = new Phone("86", "0571", "87654321", null); + pi.setFax(fax); + FullAddress addr = new FullAddress("CN", "zj", "3480", "wensanlu", "315000"); + pi.setFullAddress(addr); + pi.setMobileNo("13584652131"); + pi.setMale(true); + pi.setDepartment("b2b"); + pi.setHomepageUrl("www.capcom.com"); + pi.setJobTitle("qa"); + pi.setName("superman"); + + bigPerson.setInfoProfile(pi); + return bigPerson; + } +} diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/bytecode/WrapperTest.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/bytecode/WrapperTest.java index 86714cf2dd6e..be62ecb5e4e2 100644 --- a/dubbo-common/src/test/java/com/alibaba/dubbo/common/bytecode/WrapperTest.java +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/bytecode/WrapperTest.java @@ -13,32 +13,33 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.dubbo.common.bytecode; - -import com.alibaba.dubbo.common.bytecode.Wrapper; - -import junit.framework.TestCase; - -public class WrapperTest extends TestCase -{ - public void testMain() throws Exception - { - Wrapper w = Wrapper.getWrapper(I1.class); - String[] ns = w.getDeclaredMethodNames(); - assertEquals(ns.length, 5); - ns = w.getMethodNames(); - assertEquals(ns.length, 6); - - Object obj = new Impl1(); - assertEquals(w.getPropertyValue(obj, "name"), "you name"); - - w.setPropertyValue(obj, "name", "changed"); - assertEquals(w.getPropertyValue(obj, "name"), "changed"); +package com.alibaba.dubbo.common.bytecode; + +import org.junit.Test; +import static org.junit.Assert.*; + +public class WrapperTest +{ + @Test + public void testMain() throws Exception + { + Wrapper w = Wrapper.getWrapper(I1.class); + String[] ns = w.getDeclaredMethodNames(); + assertEquals(ns.length, 5); + ns = w.getMethodNames(); + assertEquals(ns.length, 6); + + Object obj = new Impl1(); + assertEquals(w.getPropertyValue(obj, "name"), "you name"); + + w.setPropertyValue(obj, "name", "changed"); + assertEquals(w.getPropertyValue(obj, "name"), "changed"); w.invokeMethod(obj, "hello", new Class[] {String.class}, new Object[]{ "qianlei" }); } // bug: DUBBO-132 + @Test public void test_unwantedArgument() throws Exception { Wrapper w = Wrapper.getWrapper(I1.class); Object obj = new Impl1(); @@ -51,70 +52,90 @@ public void test_unwantedArgument() throws Exception { } //bug: DUBBO-425 + @Test public void test_makeEmptyClass() throws Exception { Wrapper.getWrapper(EmptyServiceImpl.class); } - - - public static class Impl0 - { - public float a,b,c; - } - - public static interface I0 - { - String getName(); - } - - public static interface I1 extends I0 - { - void setName(String name); - - void hello(String name); - - int showInt(int v); - - void setFloat(float f); - + + /** + * see http://code.alibabatech.com/jira/browse/DUBBO-571 + */ + @Test + public void test_getDeclaredMethodNames_ContainExtendsParentMethods() throws Exception { + assertArrayEquals(new String[]{"hello", }, Wrapper.getWrapper(Parent1.class).getMethodNames()); + + assertArrayEquals(new String[]{}, Wrapper.getWrapper(Son.class).getDeclaredMethodNames()); + } + + /** + * see http://code.alibabatech.com/jira/browse/DUBBO-571 + */ + @Test + public void test_getMethodNames_ContainExtendsParentMethods() throws Exception { + assertArrayEquals(new String[]{"hello", "world"}, Wrapper.getWrapper(Son.class).getMethodNames()); + } + + public static class Impl0 + { + public float a,b,c; + } + + public static interface I0 + { + String getName(); + } + + public static interface I1 extends I0 + { + void setName(String name); + + void hello(String name); + + int showInt(int v); + + void setFloat(float f); + float getFloat(); - } - - public static class Impl1 implements I1 - { - private String name = "you name"; - - private float fv = 0; - - public String getName() - { - return name; - } - - public void setName(String name) - { - this.name = name; - } - - public void hello(String name) - { - System.out.println("hello " + name); - } - - public int showInt(int v) - { - return v; - } - - public float getFloat() - { - return fv; - } - - public void setFloat(float f) - { - fv = f; - } } + + public static class Impl1 implements I1 + { + private String name = "you name"; + + private float fv = 0; + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public void hello(String name) + { + System.out.println("hello " + name); + } + + public int showInt(int v) + { + return v; + } + + public float getFloat() + { + return fv; + } + + public void setFloat(float f) + { + fv = f; + } + } + + public static interface EmptyService { @@ -123,4 +144,16 @@ public static interface EmptyService public static class EmptyServiceImpl implements EmptyService { } + + public static interface Parent1 { + void hello(); + } + + public static interface Parent2 { + void world(); + } + + public static interface Son extends Parent1, Parent2 { + + } } \ No newline at end of file diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ExtensionLoaderTest.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ExtensionLoaderTest.java index 7e50636e59de..689d97e3f495 100644 --- a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ExtensionLoaderTest.java +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ExtensionLoaderTest.java @@ -36,10 +36,13 @@ import com.alibaba.dubbo.common.extensionloader.activate.impl.OrderActivateExtImpl2; import com.alibaba.dubbo.common.extensionloader.activate.impl.ValueActivateExtImpl; import com.alibaba.dubbo.common.extensionloader.ext1.impl.SimpleExtImpl1; -import com.alibaba.dubbo.common.extensionloader.ext1.impl.SimpleExtImpl_ManualAdd1; -import com.alibaba.dubbo.common.extensionloader.ext1.impl.SimpleExtImpl_ManualAdd2; import com.alibaba.dubbo.common.extensionloader.ext6_wrap.WrappedExt; import com.alibaba.dubbo.common.extensionloader.ext7.InitErrorExt; +import com.alibaba.dubbo.common.extensionloader.ext8_add.AddExt1; +import com.alibaba.dubbo.common.extensionloader.ext8_add.AddExt2; +import com.alibaba.dubbo.common.extensionloader.ext8_add.AddExt3; +import com.alibaba.dubbo.common.extensionloader.ext8_add.AddExt4; +import com.alibaba.dubbo.common.extensionloader.ext8_add.impl.*; import junit.framework.Assert; import org.junit.Test; @@ -219,18 +222,18 @@ public void test_getSupportedExtensions_wrapperIsNotExt() throws Exception { @Test public void test_AddExtension() throws Exception { try { - ExtensionLoader.getExtensionLoader(SimpleExt.class).getExtension("Manual1"); + ExtensionLoader.getExtensionLoader(AddExt1.class).getExtension("Manual1"); fail(); } catch (IllegalStateException expected) { - assertThat(expected.getMessage(), containsString("No such extension com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt by name Manual")); + assertThat(expected.getMessage(), containsString("No such extension com.alibaba.dubbo.common.extensionloader.ext8_add.AddExt1 by name Manual")); } - ExtensionLoader.getExtensionLoader(SimpleExt.class).addExtension("Manual1", SimpleExtImpl_ManualAdd1.class); - SimpleExt ext = ExtensionLoader.getExtensionLoader(SimpleExt.class).getExtension("Manual1"); + ExtensionLoader.getExtensionLoader(AddExt1.class).addExtension("Manual1", AddExt1_ManualAdd1.class); + AddExt1 ext = ExtensionLoader.getExtensionLoader(AddExt1.class).getExtension("Manual1"); - assertThat(ext, instanceOf(SimpleExtImpl_ManualAdd1.class)); - assertEquals("Manual1", ExtensionLoader.getExtensionLoader(SimpleExt.class).getExtensionName(SimpleExtImpl_ManualAdd1.class)); + assertThat(ext, instanceOf(AddExt1_ManualAdd1.class)); + assertEquals("Manual1", ExtensionLoader.getExtensionLoader(AddExt1.class).getExtensionName(AddExt1_ManualAdd1.class)); } @Test @@ -238,49 +241,99 @@ public void test_AddExtension_ExceptionWhenExistedExtension() throws Exception { SimpleExt ext = ExtensionLoader.getExtensionLoader(SimpleExt.class).getExtension("impl1"); try { - ExtensionLoader.getExtensionLoader(SimpleExt.class).addExtension("impl1", SimpleExtImpl_ManualAdd1.class); + ExtensionLoader.getExtensionLoader(AddExt1.class).addExtension("impl1", AddExt1_ManualAdd1.class); fail(); } catch (IllegalStateException expected) { - assertThat(expected.getMessage(), containsString("Extension name impl1 already existed(Extension interface com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt)!")); + assertThat(expected.getMessage(), containsString("Extension name impl1 already existed(Extension interface com.alibaba.dubbo.common.extensionloader.ext8_add.AddExt1)!")); + } + } + + @Test + public void test_AddExtension_Adaptive() throws Exception { + ExtensionLoader loader = ExtensionLoader.getExtensionLoader(AddExt2.class); + loader.addExtension(null, AddExt2_ManualAdaptive.class); + + AddExt2 adaptive = loader.getAdaptiveExtension(); + assertTrue(adaptive instanceof AddExt2_ManualAdaptive); + } + + @Test + public void test_AddExtension_Adaptive_ExceptionWhenExistedAdaptive() throws Exception { + ExtensionLoader loader = ExtensionLoader.getExtensionLoader(AddExt1.class); + + loader.getAdaptiveExtension(); + + try { + loader.addExtension(null, AddExt1_ManualAdaptive.class); + fail(); + } + catch (IllegalStateException expected) { + assertThat(expected.getMessage(), containsString("Adaptive Extension already existed(Extension interface com.alibaba.dubbo.common.extensionloader.ext8_add.AddExt1)!")); } } @Test public void test_replaceExtension() throws Exception { try { - ExtensionLoader.getExtensionLoader(SimpleExt.class).getExtension("Manual2"); + ExtensionLoader.getExtensionLoader(AddExt1.class).getExtension("Manual2"); fail(); } catch (IllegalStateException expected) { - assertThat(expected.getMessage(), containsString("No such extension com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt by name Manual")); + assertThat(expected.getMessage(), containsString("No such extension com.alibaba.dubbo.common.extensionloader.ext8_add.AddExt1 by name Manual")); } { - SimpleExt ext = ExtensionLoader.getExtensionLoader(SimpleExt.class).getExtension("impl1"); + AddExt1 ext = ExtensionLoader.getExtensionLoader(AddExt1.class).getExtension("impl1"); - assertThat(ext, instanceOf(SimpleExtImpl1.class)); - assertEquals("impl1", ExtensionLoader.getExtensionLoader(SimpleExt.class).getExtensionName(SimpleExtImpl1.class)); + assertThat(ext, instanceOf(AddExt1Impl1.class)); + assertEquals("impl1", ExtensionLoader.getExtensionLoader(AddExt1.class).getExtensionName(AddExt1Impl1.class)); } { - ExtensionLoader.getExtensionLoader(SimpleExt.class).replaceExtension("impl1", SimpleExtImpl_ManualAdd2.class); - SimpleExt ext = ExtensionLoader.getExtensionLoader(SimpleExt.class).getExtension("impl1"); + ExtensionLoader.getExtensionLoader(AddExt1.class).replaceExtension("impl1", AddExt1_ManualAdd2.class); + AddExt1 ext = ExtensionLoader.getExtensionLoader(AddExt1.class).getExtension("impl1"); - assertThat(ext, instanceOf(SimpleExtImpl_ManualAdd2.class)); - assertEquals("impl1", ExtensionLoader.getExtensionLoader(SimpleExt.class).getExtensionName(SimpleExtImpl_ManualAdd2.class)); + assertThat(ext, instanceOf(AddExt1_ManualAdd2.class)); + assertEquals("impl1", ExtensionLoader.getExtensionLoader(AddExt1.class).getExtensionName(AddExt1_ManualAdd2.class)); } } + @Test + public void test_replaceExtension_Adaptive() throws Exception { + ExtensionLoader loader = ExtensionLoader.getExtensionLoader(AddExt3.class); + + AddExt3 adaptive = loader.getAdaptiveExtension(); + assertFalse(adaptive instanceof AddExt3_ManualAdaptive); + + loader.replaceExtension(null, AddExt3_ManualAdaptive.class); + + adaptive = loader.getAdaptiveExtension(); + assertTrue(adaptive instanceof AddExt3_ManualAdaptive); + } + @Test public void test_replaceExtension_ExceptionWhenNotExistedExtension() throws Exception { - SimpleExt ext = ExtensionLoader.getExtensionLoader(SimpleExt.class).getExtension("impl1"); + AddExt1 ext = ExtensionLoader.getExtensionLoader(AddExt1.class).getExtension("impl1"); + + try { + ExtensionLoader.getExtensionLoader(AddExt1.class).replaceExtension("NotExistedExtension", AddExt1_ManualAdd1.class); + fail(); + } + catch (IllegalStateException expected) { + assertThat(expected.getMessage(), containsString("Extension name NotExistedExtension not existed(Extension interface com.alibaba.dubbo.common.extensionloader.ext8_add.AddExt1)")); + } + } + + @Test + public void test_replaceExtension_Adaptive_ExceptionWhenNotExistedExtension() throws Exception { + ExtensionLoader loader = ExtensionLoader.getExtensionLoader(AddExt4.class); try { - ExtensionLoader.getExtensionLoader(SimpleExt.class).replaceExtension("NotExistedExtension", SimpleExtImpl_ManualAdd1.class); + loader.replaceExtension(null, AddExt4_ManualAdaptive.class); fail(); } catch (IllegalStateException expected) { - assertThat(expected.getMessage(), containsString("Extension name NotExistedExtension not existed(Extension interface com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt)")); + assertThat(expected.getMessage(), containsString("Adaptive Extension not existed(Extension interface com.alibaba.dubbo.common.extensionloader.ext8_add.AddExt4)")); } } diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ExtensionLoader_Adaptive_Test.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ExtensionLoader_Adaptive_Test.java index 93913596848f..1d91a73505ab 100644 --- a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ExtensionLoader_Adaptive_Test.java +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ExtensionLoader_Adaptive_Test.java @@ -17,6 +17,8 @@ import com.alibaba.dubbo.common.URL; import com.alibaba.dubbo.common.extension.ExtensionLoader; +import com.alibaba.dubbo.common.extensionloader.adaptive.HasAdaptiveExt; +import com.alibaba.dubbo.common.extensionloader.adaptive.impl.HasAdaptiveExt_ManualAdaptive; import com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt; import com.alibaba.dubbo.common.extensionloader.ext2.Ext2; import com.alibaba.dubbo.common.extensionloader.ext2.UrlHolder; @@ -39,6 +41,14 @@ * @author ding.lid */ public class ExtensionLoader_Adaptive_Test { + + @Test + public void test_useAdaptiveClass() throws Exception { + ExtensionLoader loader = ExtensionLoader.getExtensionLoader(HasAdaptiveExt.class); + HasAdaptiveExt ext = loader.getAdaptiveExtension(); + assertTrue(ext instanceof HasAdaptiveExt_ManualAdaptive); + } + @Test public void test_getAdaptiveExtension_defaultAdaptiveKey() throws Exception { { diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/adaptive/HasAdaptiveExt.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/adaptive/HasAdaptiveExt.java new file mode 100644 index 000000000000..442b169c2f56 --- /dev/null +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/adaptive/HasAdaptiveExt.java @@ -0,0 +1,14 @@ +package com.alibaba.dubbo.common.extensionloader.adaptive; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.extension.Adaptive; +import com.alibaba.dubbo.common.extension.SPI; + +/** + * @author ding.lid + */ +@SPI +public interface HasAdaptiveExt { + @Adaptive + String echo(URL url, String s); +} diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext1/impl/SimpleExtImpl_ManualAdd1.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/adaptive/impl/HasAdaptiveExtImpl1.java similarity index 65% rename from dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext1/impl/SimpleExtImpl_ManualAdd1.java rename to dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/adaptive/impl/HasAdaptiveExtImpl1.java index 28ab01befa00..7589cd466e95 100644 --- a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext1/impl/SimpleExtImpl_ManualAdd1.java +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/adaptive/impl/HasAdaptiveExtImpl1.java @@ -13,25 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.dubbo.common.extensionloader.ext1.impl; +package com.alibaba.dubbo.common.extensionloader.adaptive.impl; import com.alibaba.dubbo.common.URL; -import com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt; +import com.alibaba.dubbo.common.extensionloader.adaptive.HasAdaptiveExt; /** * @author ding.lid */ -public class SimpleExtImpl_ManualAdd1 implements SimpleExt { +public class HasAdaptiveExtImpl1 implements HasAdaptiveExt { public String echo(URL url, String s) { - return "Ext1Impl4-echo"; + return this.getClass().getSimpleName(); } - - public String yell(URL url, String s) { - return "Ext1Impl4-yell"; - } - - public String bang(URL url, int i) { - return "bang4"; - } - } \ No newline at end of file diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/adaptive/impl/HasAdaptiveExt_ManualAdaptive.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/adaptive/impl/HasAdaptiveExt_ManualAdaptive.java new file mode 100644 index 000000000000..9918b3144e11 --- /dev/null +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/adaptive/impl/HasAdaptiveExt_ManualAdaptive.java @@ -0,0 +1,32 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.extensionloader.adaptive.impl; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.extension.Adaptive; +import com.alibaba.dubbo.common.extension.ExtensionLoader; +import com.alibaba.dubbo.common.extensionloader.adaptive.HasAdaptiveExt; + +/** + * @author ding.lid + */ +@Adaptive +public class HasAdaptiveExt_ManualAdaptive implements HasAdaptiveExt { + public String echo(URL url, String s) { + HasAdaptiveExt addExt1 = ExtensionLoader.getExtensionLoader(HasAdaptiveExt.class).getExtension(url.getParameter("key")); + return addExt1.echo(url, s); + } +} \ No newline at end of file diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/compatible/CompatibleExt.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/compatible/CompatibleExt.java index 21b3eb183f75..b08340d25753 100644 --- a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/compatible/CompatibleExt.java +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/compatible/CompatibleExt.java @@ -20,7 +20,6 @@ import com.alibaba.dubbo.common.extension.SPI; /** - * * @author ding.lid */ @SPI("impl1") diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/AddExt1.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/AddExt1.java new file mode 100644 index 000000000000..4d6889d987d0 --- /dev/null +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/AddExt1.java @@ -0,0 +1,31 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.extensionloader.ext8_add; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.extension.Adaptive; +import com.alibaba.dubbo.common.extension.SPI; + +/** + * show add extension pragmatically + * + * @author ding.lid + */ +@SPI("impl1") +public interface AddExt1 { + @Adaptive + String echo(URL url, String s); +} \ No newline at end of file diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/AddExt2.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/AddExt2.java new file mode 100644 index 000000000000..e088fd60a96e --- /dev/null +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/AddExt2.java @@ -0,0 +1,31 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.extensionloader.ext8_add; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.extension.Adaptive; +import com.alibaba.dubbo.common.extension.SPI; + +/** + * show add extension pragmatically. use for test addAdaptive successful + * + * @author ding.lid + */ +@SPI("impl1") +public interface AddExt2 { + @Adaptive + String echo(URL url, String s); +} \ No newline at end of file diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/AddExt3.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/AddExt3.java new file mode 100644 index 000000000000..d585228d4cfe --- /dev/null +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/AddExt3.java @@ -0,0 +1,31 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.extensionloader.ext8_add; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.extension.Adaptive; +import com.alibaba.dubbo.common.extension.SPI; + +/** + * show add extension pragmatically. use for test replaceAdaptive success + * + * @author ding.lid + */ +@SPI("impl1") +public interface AddExt3 { + @Adaptive + String echo(URL url, String s); +} \ No newline at end of file diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/AddExt4.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/AddExt4.java new file mode 100644 index 000000000000..633b58374b57 --- /dev/null +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/AddExt4.java @@ -0,0 +1,31 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.extensionloader.ext8_add; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.extension.Adaptive; +import com.alibaba.dubbo.common.extension.SPI; + +/** + * show add extension pragmatically. use for test replaceAdaptive fail + * + * @author ding.lid + */ +@SPI("impl1") +public interface AddExt4 { + @Adaptive + String echo(URL url, String s); +} \ No newline at end of file diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext1/impl/SimpleExtImpl_ManualAdd2.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt1Impl1.java similarity index 65% rename from dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext1/impl/SimpleExtImpl_ManualAdd2.java rename to dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt1Impl1.java index b2685bc75e84..b1a48fc8c825 100644 --- a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext1/impl/SimpleExtImpl_ManualAdd2.java +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt1Impl1.java @@ -13,25 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.dubbo.common.extensionloader.ext1.impl; +package com.alibaba.dubbo.common.extensionloader.ext8_add.impl; import com.alibaba.dubbo.common.URL; -import com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt; +import com.alibaba.dubbo.common.extensionloader.ext8_add.AddExt1; /** * @author ding.lid */ -public class SimpleExtImpl_ManualAdd2 implements SimpleExt { +public class AddExt1Impl1 implements AddExt1 { public String echo(URL url, String s) { - return "Ext1Impl4-echo"; + return this.getClass().getSimpleName(); } - - public String yell(URL url, String s) { - return "Ext1Impl4-yell"; - } - - public String bang(URL url, int i) { - return "bang4"; - } - } \ No newline at end of file diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt1_ManualAdaptive.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt1_ManualAdaptive.java new file mode 100644 index 000000000000..7edce0da8d2c --- /dev/null +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt1_ManualAdaptive.java @@ -0,0 +1,32 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.extensionloader.ext8_add.impl; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.extension.Adaptive; +import com.alibaba.dubbo.common.extension.ExtensionLoader; +import com.alibaba.dubbo.common.extensionloader.ext8_add.AddExt1; + +/** + * @author ding.lid + */ +@Adaptive +public class AddExt1_ManualAdaptive implements AddExt1 { + public String echo(URL url, String s) { + AddExt1 addExt1 = ExtensionLoader.getExtensionLoader(AddExt1.class).getExtension(url.getParameter("add.ext1")); + return addExt1.echo(url, s); + } +} \ No newline at end of file diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt1_ManualAdd1.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt1_ManualAdd1.java new file mode 100644 index 000000000000..ab7e2671cb18 --- /dev/null +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt1_ManualAdd1.java @@ -0,0 +1,28 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.extensionloader.ext8_add.impl; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.extensionloader.ext8_add.AddExt1; + +/** + * @author ding.lid + */ +public class AddExt1_ManualAdd1 implements AddExt1 { + public String echo(URL url, String s) { + return this.getClass().getSimpleName(); + } +} \ No newline at end of file diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt1_ManualAdd2.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt1_ManualAdd2.java new file mode 100644 index 000000000000..d7faf3438854 --- /dev/null +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt1_ManualAdd2.java @@ -0,0 +1,28 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.extensionloader.ext8_add.impl; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.extensionloader.ext8_add.AddExt1; + +/** + * @author ding.lid + */ +public class AddExt1_ManualAdd2 implements AddExt1 { + public String echo(URL url, String s) { + return this.getClass().getSimpleName(); + } +} \ No newline at end of file diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt2Impl1.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt2Impl1.java new file mode 100644 index 000000000000..176e68b3ce5c --- /dev/null +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt2Impl1.java @@ -0,0 +1,28 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.extensionloader.ext8_add.impl; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.extensionloader.ext8_add.AddExt2; + +/** + * @author ding.lid + */ +public class AddExt2Impl1 implements AddExt2 { + public String echo(URL url, String s) { + return this.getClass().getSimpleName(); + } +} \ No newline at end of file diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt2_ManualAdaptive.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt2_ManualAdaptive.java new file mode 100644 index 000000000000..ee26bcf3addf --- /dev/null +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt2_ManualAdaptive.java @@ -0,0 +1,32 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.extensionloader.ext8_add.impl; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.extension.Adaptive; +import com.alibaba.dubbo.common.extension.ExtensionLoader; +import com.alibaba.dubbo.common.extensionloader.ext8_add.AddExt2; + +/** + * @author ding.lid + */ +@Adaptive +public class AddExt2_ManualAdaptive implements AddExt2 { + public String echo(URL url, String s) { + AddExt2 addExt1 = ExtensionLoader.getExtensionLoader(AddExt2.class).getExtension(url.getParameter("add.ext2")); + return addExt1.echo(url, s); + } +} \ No newline at end of file diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt3_ManualAdaptive.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt3_ManualAdaptive.java new file mode 100644 index 000000000000..dd752dd43d80 --- /dev/null +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt3_ManualAdaptive.java @@ -0,0 +1,32 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.extensionloader.ext8_add.impl; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.extension.Adaptive; +import com.alibaba.dubbo.common.extension.ExtensionLoader; +import com.alibaba.dubbo.common.extensionloader.ext8_add.AddExt3; + +/** + * @author ding.lid + */ +@Adaptive +public class AddExt3_ManualAdaptive implements AddExt3 { + public String echo(URL url, String s) { + AddExt3 addExt1 = ExtensionLoader.getExtensionLoader(AddExt3.class).getExtension(url.getParameter("add.ext3")); + return addExt1.echo(url, s); + } +} \ No newline at end of file diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt4_ManualAdaptive.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt4_ManualAdaptive.java new file mode 100644 index 000000000000..9cf5921d8d5f --- /dev/null +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext8_add/impl/AddExt4_ManualAdaptive.java @@ -0,0 +1,32 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.extensionloader.ext8_add.impl; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.extension.Adaptive; +import com.alibaba.dubbo.common.extension.ExtensionLoader; +import com.alibaba.dubbo.common.extensionloader.ext8_add.AddExt4; + +/** + * @author ding.lid + */ +@Adaptive +public class AddExt4_ManualAdaptive implements AddExt4 { + public String echo(URL url, String s) { + AddExt4 addExt1 = ExtensionLoader.getExtensionLoader(AddExt4.class).getExtension(url.getParameter("add.ext4")); + return addExt1.echo(url, s); + } +} \ No newline at end of file diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/json/JacksonTest.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/json/JacksonTest.java new file mode 100644 index 000000000000..558e9735bfdc --- /dev/null +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/json/JacksonTest.java @@ -0,0 +1,177 @@ +package com.alibaba.dubbo.common.json; + +import com.alibaba.dubbo.common.serialize.support.json.FastJsonObjectOutput; +import com.alibaba.dubbo.common.serialize.support.json.JacksonObjectInput; +import com.alibaba.dubbo.common.serialize.support.json.JacksonObjectOutput; +import com.alibaba.dubbo.common.utils.CollectionUtils; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; + +import java.io.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Created by dylan on 11/13/14. + */ +public class JacksonTest { + @Test + public void testWrite() throws Exception{ + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + JacksonObjectOutput output = new JacksonObjectOutput(bos); +// PrintWriter writer = new PrintWriter(new OutputStreamWriter(System.out)); + output.writeUTF("2.0.0"); + output.writeBool(true); + output.writeByte((byte) 2); + output.writeBytes(new String("abc").getBytes()); + output.writeDouble(2.0d); + output.writeFloat(3.05f); + output.writeInt(32); + output.writeLong(64L); + output.writeShort((short) 16); + output.writeBytes(new String("afdsafdsafsa").getBytes(), 6, 4); + output.writeObject(new String[]{"abc", "def", "gfk"}); + output.writeObject(new int[]{4,5,8}); + output.writeObject(new JacksonBean()); + output.flushBuffer(); + + JacksonObjectInput input = new JacksonObjectInput(new ByteArrayInputStream(bos.toByteArray())); + System.out.println(input.readUTF()); + System.out.println(input.readBool()); + System.out.println(input.readByte()); + System.out.println(new String(input.readBytes())); + System.out.println(input.readDouble()); + System.out.println(input.readFloat()); + System.out.println(input.readInt()); + System.out.println(input.readLong()); + System.out.println(input.readShort()); + System.out.println(Arrays.toString(input.readBytes())); + System.out.println(Arrays.toString(input.readObject(String[].class))); + System.out.println(Arrays.toString(input.readObject(int[].class))); + JacksonBean jacksonBean = input.readObject(JacksonBean.class); + System.out.println(jacksonBean); + + } + public static class JacksonBean { + private boolean bValue = true; + private String sValue = "string"; + private int iValue = 20; + private double dValue = 20.5; + private float fValue = 2.18f; + private long lValue = 3; + private Double dValue2 = null; + private List innerBeanList = new ArrayList(); + + public JacksonBean(){ + innerBeanList.add(new InnerBean()); + innerBeanList.add(new InnerBean()); + } + @Override + public String toString() { + return "JacksonBean{" + + "bValue=" + bValue + + ", sValue='" + sValue + '\'' + + ", iValue=" + iValue + + ", dValue=" + dValue + + ", fValue=" + fValue + + ", lValue=" + lValue + + ", dValue2=" + dValue2 + + ", innerBeanList=" + innerBeanList + + '}'; + } + + public boolean isbValue() { + return bValue; + } + + public void setbValue(boolean bValue) { + this.bValue = bValue; + } + + public String getsValue() { + return sValue; + } + + public void setsValue(String sValue) { + this.sValue = sValue; + } + + public int getiValue() { + return iValue; + } + + public void setiValue(int iValue) { + this.iValue = iValue; + } + + public double getdValue() { + return dValue; + } + + public void setdValue(double dValue) { + this.dValue = dValue; + } + + public float getfValue() { + return fValue; + } + + public void setfValue(float fValue) { + this.fValue = fValue; + } + + public long getlValue() { + return lValue; + } + + public void setlValue(long lValue) { + this.lValue = lValue; + } + + public Double getdValue2() { + return dValue2; + } + + public void setdValue2(Double dValue2) { + this.dValue2 = dValue2; + } + + public List getInnerBeanList() { + return innerBeanList; + } + + public void setInnerBeanList(List innerBeanList) { + this.innerBeanList = innerBeanList; + } + } + + public static class InnerBean { + private String siValue = "innerStr"; + private int iiValue = 18; + + public String getSiValue() { + return siValue; + } + + public void setSiValue(String siValue) { + this.siValue = siValue; + } + + public int getIiValue() { + return iiValue; + } + + public void setIiValue(int iiValue) { + this.iiValue = iiValue; + } + + @Override + public String toString() { + return "InnerBean{" + + "siValue='" + siValue + '\'' + + ", iiValue=" + iiValue + + '}'; + } + } +} diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/serialize/serialization/FstSerializationTest.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/serialize/serialization/FstSerializationTest.java new file mode 100644 index 000000000000..02932765df59 --- /dev/null +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/serialize/serialization/FstSerializationTest.java @@ -0,0 +1,13 @@ +package com.alibaba.dubbo.common.serialize.serialization; + +import com.alibaba.dubbo.common.serialize.support.kryo.KryoSerialization; + +/** + * @author lishen + */ +public class FstSerializationTest extends AbstractSerializationTest { + + { + serialization = new KryoSerialization(); + } +} diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/serialize/serialization/KyroSerializationTest.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/serialize/serialization/KyroSerializationTest.java new file mode 100644 index 000000000000..244a49fa1d49 --- /dev/null +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/serialize/serialization/KyroSerializationTest.java @@ -0,0 +1,13 @@ +package com.alibaba.dubbo.common.serialize.serialization; + +import com.alibaba.dubbo.common.serialize.support.kryo.KryoSerialization; + +/** + * @author lishen + */ +public class KyroSerializationTest extends AbstractSerializationTest { + + { + serialization = new KryoSerialization(); + } +} \ No newline at end of file diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/serialize/serialization/ReflectionUtilsTest.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/serialize/serialization/ReflectionUtilsTest.java new file mode 100644 index 000000000000..f4ef790ec6eb --- /dev/null +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/serialize/serialization/ReflectionUtilsTest.java @@ -0,0 +1,34 @@ +package com.alibaba.dubbo.common.serialize.serialization; + +import com.alibaba.dubbo.common.serialize.support.kryo.ReflectionUtils; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + + + +/** + * @author lishen + */ +public class ReflectionUtilsTest { + + @Test + public void test() { + assertTrue(ReflectionUtils.checkZeroArgConstructor(String.class)); + assertTrue(ReflectionUtils.checkZeroArgConstructor(Bar.class)); + assertFalse(ReflectionUtils.checkZeroArgConstructor(Foo.class)); + } + + static class Foo { + public Foo(int i) { + + } + } + + static class Bar { + private Bar() { + + } + } +} diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/utils/PojoUtilsTest.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/utils/PojoUtilsTest.java index dc346389dabe..7e4d04502fc0 100644 --- a/dubbo-common/src/test/java/com/alibaba/dubbo/common/utils/PojoUtilsTest.java +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/utils/PojoUtilsTest.java @@ -614,6 +614,79 @@ public void testRealizeLinkedList() throws Exception { Assert.assertTrue(output instanceof LinkedList); } + @Test + public void testPojoList() throws Exception { + ListResult result = new ListResult(); + List list = new ArrayList(); + Parent parent = new Parent(); + parent.setAge(Integer.MAX_VALUE); + parent.setName("zhangsan"); + list.add(parent); + result.setResult(list); + + Object generializeObject = PojoUtils.generalize(result); + Object realizeObject = PojoUtils.realize(generializeObject, ListResult.class); + Assert.assertTrue(realizeObject instanceof ListResult); + ListResult listResult = (ListResult)realizeObject; + List l = listResult.getResult(); + Assert.assertTrue(l.size() == 1); + Assert.assertTrue(l.get(0) instanceof Parent); + Parent realizeParent = (Parent)l.get(0); + Assert.assertEquals(parent.getName(), realizeParent.getName()); + Assert.assertEquals(parent.getAge(), realizeParent.getAge()); + } + + @Test + public void testListPojoListPojo() throws Exception { + InnerPojo parentList = new InnerPojo(); + Parent parent = new Parent(); + parent.setName("zhangsan"); + parent.setAge(Integer.MAX_VALUE); + parentList.setList(Arrays.asList(parent)); + + ListResult> list = new ListResult>(); + list.setResult(Arrays.asList(parentList)); + + Object generializeObject = PojoUtils.generalize(list); + Object realizeObject = PojoUtils.realize(generializeObject, ListResult.class); + + Assert.assertTrue(realizeObject instanceof ListResult); + ListResult realizeList = (ListResult)realizeObject; + List realizeInnerList = realizeList.getResult(); + Assert.assertEquals(1, realizeInnerList.size()); + Assert.assertTrue(realizeInnerList.get(0) instanceof InnerPojo); + InnerPojo realizeParentList = (InnerPojo)realizeInnerList.get(0); + Assert.assertEquals(1, realizeParentList.getList().size()); + Assert.assertTrue(realizeParentList.getList().get(0) instanceof Parent); + Parent realizeParent = (Parent)realizeParentList.getList().get(0); + Assert.assertEquals(parent.getName(), realizeParent.getName()); + Assert.assertEquals(parent.getAge(), realizeParent.getAge()); + } + + public static class InnerPojo { + private List list; + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + } + + public static class ListResult { + List result; + + public List getResult() { + return result; + } + + public void setResult(List result) { + this.result = result; + } + } + private static Child newChild(String name, int age) { Child result = new Child(); result.setName(name); diff --git a/dubbo-common/src/test/resources/META-INF/dubbo/internal/com.alibaba.dubbo.common.extensionloader.adaptive.HasAdaptiveExt b/dubbo-common/src/test/resources/META-INF/dubbo/internal/com.alibaba.dubbo.common.extensionloader.adaptive.HasAdaptiveExt new file mode 100644 index 000000000000..c700dbd7c263 --- /dev/null +++ b/dubbo-common/src/test/resources/META-INF/dubbo/internal/com.alibaba.dubbo.common.extensionloader.adaptive.HasAdaptiveExt @@ -0,0 +1,2 @@ +adaptive=com.alibaba.dubbo.common.extensionloader.adaptive.impl.HasAdaptiveExt_ManualAdaptive +impl1=com.alibaba.dubbo.common.extensionloader.adaptive.impl.HasAdaptiveExtImpl1 \ No newline at end of file diff --git a/dubbo-common/src/test/resources/META-INF/dubbo/internal/com.alibaba.dubbo.common.extensionloader.ext8_add.AddExt1 b/dubbo-common/src/test/resources/META-INF/dubbo/internal/com.alibaba.dubbo.common.extensionloader.ext8_add.AddExt1 new file mode 100644 index 000000000000..02ee0c0f5ca9 --- /dev/null +++ b/dubbo-common/src/test/resources/META-INF/dubbo/internal/com.alibaba.dubbo.common.extensionloader.ext8_add.AddExt1 @@ -0,0 +1 @@ +impl1=com.alibaba.dubbo.common.extensionloader.ext8_add.impl.AddExt1Impl1 \ No newline at end of file diff --git a/dubbo-config/dubbo-config-api/pom.xml b/dubbo-config/dubbo-config-api/pom.xml index 3819ef32d8b1..d1f6a82c9c8c 100644 --- a/dubbo-config/dubbo-config-api/pom.xml +++ b/dubbo-config/dubbo-config-api/pom.xml @@ -1,12 +1,12 @@ + \ No newline at end of file diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/AnnotationBean.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/AnnotationBean.java index c4c5d048fada..8f54baacee88 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/AnnotationBean.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/AnnotationBean.java @@ -24,7 +24,9 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import org.springframework.aop.support.AopUtils; import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanInitializationException; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.BeanPostProcessor; @@ -134,15 +136,19 @@ public Object postProcessAfterInitialization(Object bean, String beanName) if (! isMatchPackage(bean)) { return bean; } - Service service = bean.getClass().getAnnotation(Service.class); + Class clazz = bean.getClass(); + if(isProxyBean(bean)){ + clazz = AopUtils.getTargetClass(bean); + } + Service service = clazz.getAnnotation(Service.class); if (service != null) { ServiceBean serviceConfig = new ServiceBean(service); if (void.class.equals(service.interfaceClass()) && "".equals(service.interfaceName())) { - if (bean.getClass().getInterfaces().length > 0) { - serviceConfig.setInterface(bean.getClass().getInterfaces()[0]); + if (clazz.getInterfaces().length > 0) { + serviceConfig.setInterface(clazz.getInterfaces()[0]); } else { - throw new IllegalStateException("Failed to export remote service class " + bean.getClass().getName() + ", cause: The @Service undefined interfaceClass or interfaceName, and the service class unimplemented any interfaces."); + throw new IllegalStateException("Failed to export remote service class " + clazz.getName() + ", cause: The @Service undefined interfaceClass or interfaceName, and the service class unimplemented any interfaces."); } } if (applicationContext != null) { @@ -175,7 +181,8 @@ public Object postProcessAfterInitialization(Object bean, String beanName) } if (service.protocol() != null && service.protocol().length > 0) { List protocolConfigs = new ArrayList(); - for (String protocolId : service.registry()) { + // modified by lishen; fix dubbo's bug + for (String protocolId : service.protocol()) { if (protocolId != null && protocolId.length() > 0) { protocolConfigs.add((ProtocolConfig)applicationContext.getBean(protocolId, ProtocolConfig.class)); } @@ -202,7 +209,11 @@ public Object postProcessBeforeInitialization(Object bean, String beanName) if (! isMatchPackage(bean)) { return bean; } - Method[] methods = bean.getClass().getMethods(); + Class clazz = bean.getClass(); + if(isProxyBean(bean)){ + clazz = AopUtils.getTargetClass(bean); + } + Method[] methods = clazz.getMethods(); for (Method method : methods) { String name = method.getName(); if (name.length() > 3 && name.startsWith("set") @@ -214,15 +225,17 @@ public Object postProcessBeforeInitialization(Object bean, String beanName) if (reference != null) { Object value = refer(reference, method.getParameterTypes()[0]); if (value != null) { - method.invoke(bean, new Object[] { }); + method.invoke(bean, new Object[] { value }); } } - } catch (Throwable e) { - logger.error("Failed to init remote service reference at method " + name + " in class " + bean.getClass().getName() + ", cause: " + e.getMessage(), e); + } catch (Exception e) { + // modified by lishen + throw new BeanInitializationException("Failed to init remote service reference at method " + name + " in class " + bean.getClass().getName(), e); +// logger.error("Failed to init remote service reference at method " + name + " in class " + bean.getClass().getName() + ", cause: " + e.getMessage(), e); } } } - Field[] fields = bean.getClass().getDeclaredFields(); + Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { try { if (! field.isAccessible()) { @@ -235,8 +248,10 @@ public Object postProcessBeforeInitialization(Object bean, String beanName) field.set(bean, value); } } - } catch (Throwable e) { - logger.error("Failed to init remote service reference at filed " + field.getName() + " in class " + bean.getClass().getName() + ", cause: " + e.getMessage(), e); + } catch (Exception e) { + // modified by lishen + throw new BeanInitializationException("Failed to init remote service reference at filed " + field.getName() + " in class " + bean.getClass().getName(), e); +// logger.error("Failed to init remote service reference at filed " + field.getName() + " in class " + bean.getClass().getName() + ", cause: " + e.getMessage(), e); } } return bean; @@ -306,7 +321,11 @@ private boolean isMatchPackage(Object bean) { if (annotationPackages == null || annotationPackages.length == 0) { return true; } - String beanClassName = bean.getClass().getName(); + Class clazz = bean.getClass(); + if(isProxyBean(bean)){ + clazz = AopUtils.getTargetClass(bean); + } + String beanClassName = clazz.getName(); for (String pkg : annotationPackages) { if (beanClassName.startsWith(pkg)) { return true; @@ -315,4 +334,8 @@ private boolean isMatchPackage(Object bean) { return false; } + private boolean isProxyBean(Object bean) { + return AopUtils.isAopProxy(bean); + } + } diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/ServiceBean.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/ServiceBean.java index 0f3ff57196be..cc9c2a0776a3 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/ServiceBean.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/ServiceBean.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Map; +import org.springframework.aop.support.AopUtils; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.DisposableBean; @@ -255,4 +256,12 @@ public void destroy() throws Exception { unexport(); } + // added by lishen + @Override + protected Class getServiceClass(T ref) { + if (AopUtils.isAopProxy(ref)) { + return AopUtils.getTargetClass(ref); + } + return super.getServiceClass(ref); + } } \ No newline at end of file diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd index cccbb79b899b..d0168856cd42 100644 --- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd +++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd @@ -589,6 +589,11 @@ + + + + + @@ -773,6 +778,28 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -825,7 +852,12 @@ - + + + + + + @@ -945,7 +977,12 @@ - + + + + + + @@ -1041,6 +1078,11 @@ + + + + + diff --git a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/ConfigTest.java b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/ConfigTest.java index c3c3d2460cf6..71d81d3d7af7 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/ConfigTest.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/ConfigTest.java @@ -23,12 +23,15 @@ import static org.junit.Assert.fail; import static org.junit.matchers.JUnitMatchers.containsString; +import java.util.Collection; import java.util.List; import org.junit.Test; +import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanCreationException; import org.springframework.context.support.ClassPathXmlApplicationContext; +import com.alibaba.dubbo.common.Constants; import com.alibaba.dubbo.common.URL; import com.alibaba.dubbo.common.extension.ExtensionLoader; import com.alibaba.dubbo.common.utils.NetUtils; @@ -48,11 +51,17 @@ import com.alibaba.dubbo.config.spring.filter.MockFilter; import com.alibaba.dubbo.config.spring.impl.DemoServiceImpl; import com.alibaba.dubbo.config.spring.impl.HelloServiceImpl; +import com.alibaba.dubbo.config.spring.registry.MockRegistry; +import com.alibaba.dubbo.config.spring.registry.MockRegistryFactory; +import com.alibaba.dubbo.registry.Registry; +import com.alibaba.dubbo.registry.RegistryFactory; import com.alibaba.dubbo.registry.RegistryService; import com.alibaba.dubbo.rpc.Exporter; import com.alibaba.dubbo.rpc.Filter; import com.alibaba.dubbo.rpc.RpcContext; import com.alibaba.dubbo.rpc.RpcException; +import com.alibaba.dubbo.rpc.service.GenericException; +import com.alibaba.dubbo.rpc.service.GenericService; import junit.framework.Assert; @@ -368,6 +377,23 @@ public void testInitReference() throws Exception { providerContext.close(); } } + + // DUBBO-571 Provider的URL的methods key值中没有继承接口的方法 + @Test + public void test_noMethodInterface_methodsKeyHasValue() throws Exception { + ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(ConfigTest.class.getPackage().getName().replace('.', '/') + "/demo-provider-no-methods-interface.xml"); + ctx.start(); + try { + ServiceBean bean = (ServiceBean) ctx.getBean("service"); + List urls = bean.getExportedUrls(); + assertEquals(1, urls.size()); + URL url = urls.get(0); + assertEquals("sayName,getBox", url.getParameter("methods")); + } finally { + ctx.stop(); + ctx.close(); + } + } // DUBBO-147 通过RpcContext可以获得所有尝试过的Invoker @Test @@ -884,6 +910,78 @@ public void testProtocolRandomPort() throws Exception { } } + @Test + public void testReferGenericExport() throws Exception { + ApplicationConfig ac = new ApplicationConfig("test-refer-generic-export"); + RegistryConfig rc = new RegistryConfig(); + rc.setAddress(RegistryConfig.NO_AVAILABLE); + + ServiceConfig sc = new ServiceConfig(); + sc.setApplication(ac); + sc.setRegistry(rc); + sc.setInterface(DemoService.class.getName()); + sc.setRef(new GenericService() { + + public Object $invoke(String method, String[] parameterTypes, Object[] args) throws GenericException { + return null; + } + }); + + ReferenceConfig ref = new ReferenceConfig(); + ref.setApplication(ac); + ref.setRegistry(rc); + ref.setInterface(DemoService.class.getName()); + + try { + sc.export(); + ref.get(); + Assert.fail(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + sc.unexport(); + ref.destroy(); + } + } + + @Test + public void testGenericServiceConfig() throws Exception { + ServiceConfig service = new ServiceConfig(); + service.setApplication(new ApplicationConfig("test")); + service.setRegistry(new RegistryConfig("mock://localhost")); + service.setInterface(DemoService.class.getName()); + service.setGeneric(Constants.GENERIC_SERIALIZATION_BEAN); + service.setRef(new GenericService(){ + + public Object $invoke(String method, String[] parameterTypes, Object[] args) throws GenericException { + return null; + } + }); + try { + service.export(); + Collection collection = MockRegistryFactory.getCachedRegistry(); + MockRegistry registry = (MockRegistry)collection.iterator().next(); + URL url = registry.getRegistered().get(0); + Assert.assertEquals(Constants.GENERIC_SERIALIZATION_BEAN, url.getParameter(Constants.GENERIC_KEY)); + } finally { + MockRegistryFactory.cleanCachedRegistry(); + service.unexport(); + } + } + + @Test + public void testGenericServiceConfigThroughSpring() throws Exception { + ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(ConfigTest.class.getPackage().getName().replace('.', '/') + "/generic-export.xml"); + try { + ctx.start(); + ServiceConfig serviceConfig = (ServiceConfig) ctx.getBean("dubboDemoService"); + URL url = (URL)serviceConfig.getExportedUrls().get(0); + Assert.assertEquals(Constants.GENERIC_SERIALIZATION_BEAN, url.getParameter(Constants.GENERIC_KEY)); + } finally { + ctx.destroy(); + } + } + private static void unexportService(ServiceConfig config) { if (config != null) { config.unexport(); diff --git a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/GenericDemoService.java b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/GenericDemoService.java new file mode 100644 index 000000000000..6fa81cda2d38 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/GenericDemoService.java @@ -0,0 +1,14 @@ +package com.alibaba.dubbo.config.spring; + +import com.alibaba.dubbo.rpc.service.GenericException; +import com.alibaba.dubbo.rpc.service.GenericService; + +/** + * @author kimi + */ +public class GenericDemoService implements GenericService { + + public Object $invoke(String method, String[] parameterTypes, Object[] args) throws GenericException { + return null; + } +} diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/DemoService.java b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/api/DemoServiceSon.java similarity index 78% rename from dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/DemoService.java rename to dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/api/DemoServiceSon.java index 7dda95f2d799..ede66ebc8bac 100644 --- a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/DemoService.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/api/DemoServiceSon.java @@ -1,22 +1,25 @@ -/* - * Copyright 1999-2011 Alibaba Group. - * - * Licensed 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.demo; - -public interface DemoService { - - String sayHello(String name); - +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.spring.api; + +/** + * DemoService + * + * @author ding.lid + */ +public interface DemoServiceSon extends DemoService { + // no methods } \ No newline at end of file diff --git a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/impl/DemoServiceSonImpl.java b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/impl/DemoServiceSonImpl.java new file mode 100644 index 000000000000..1a0292207218 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/impl/DemoServiceSonImpl.java @@ -0,0 +1,45 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.spring.impl; + +import com.alibaba.dubbo.config.spring.api.Box; +import com.alibaba.dubbo.config.spring.api.DemoService; +import com.alibaba.dubbo.config.spring.api.DemoServiceSon; + +/** + * @author ding.lid + */ +public class DemoServiceSonImpl implements DemoServiceSon { + + private String prefix = "say:"; + + public String sayName(String name) { + return prefix + name; + } + + public Box getBox() { + return null; + } + + public String getPrefix() { + return prefix; + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + } + +} \ No newline at end of file diff --git a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/registry/MockRegistry.java b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/registry/MockRegistry.java new file mode 100644 index 000000000000..5ac78b31d68e --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/registry/MockRegistry.java @@ -0,0 +1,67 @@ +package com.alibaba.dubbo.config.spring.registry; + +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.registry.NotifyListener; +import com.alibaba.dubbo.registry.Registry; + +/** + * @author kimi + */ +public class MockRegistry implements Registry { + + private URL url; + + private List registered = new ArrayList(); + + private List subscribered = new ArrayList(); + + public List getRegistered() { + return registered; + } + + public List getSubscribered() { + return subscribered; + } + + public MockRegistry(URL url) { + if (url == null) { + throw new NullPointerException(); + } + this.url = url; + } + + public URL getUrl() { + return url; + } + + public boolean isAvailable() { + return true; + } + + public void destroy() { + + } + + public void register(URL url) { + registered.add(url); + } + + public void unregister(URL url) { + registered.remove(url); + } + + public void subscribe(URL url, NotifyListener listener) { + subscribered.add(url); + } + + public void unsubscribe(URL url, NotifyListener listener) { + subscribered.remove(url); + } + + public List lookup(URL url) { + return null; + } +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/registry/MockRegistryFactory.java b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/registry/MockRegistryFactory.java new file mode 100644 index 000000000000..d7178fcde392 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/registry/MockRegistryFactory.java @@ -0,0 +1,31 @@ +package com.alibaba.dubbo.config.spring.registry; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.registry.Registry; +import com.alibaba.dubbo.registry.RegistryFactory; + +/** + * @author kimi + */ +public class MockRegistryFactory implements RegistryFactory { + + private static final Map registries = new HashMap(); + + public Registry getRegistry(URL url) { + MockRegistry registry = new MockRegistry(url); + registries.put(url, registry); + return registry; + } + + public static Collection getCachedRegistry() { + return registries.values(); + } + + public static void cleanCachedRegistry() { + registries.clear(); + } +} diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbo/internal/com.alibaba.dubbo.registry.RegistryFactory b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbo/internal/com.alibaba.dubbo.registry.RegistryFactory new file mode 100644 index 000000000000..a6fed7ef8106 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbo/internal/com.alibaba.dubbo.registry.RegistryFactory @@ -0,0 +1 @@ +mock=com.alibaba.dubbo.config.spring.registry.MockRegistryFactory \ No newline at end of file diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/com/alibaba/dubbo/config/spring/demo-provider-no-methods-interface.xml b/dubbo-config/dubbo-config-spring/src/test/resources/com/alibaba/dubbo/config/spring/demo-provider-no-methods-interface.xml new file mode 100644 index 000000000000..260d21f4e760 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/test/resources/com/alibaba/dubbo/config/spring/demo-provider-no-methods-interface.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/com/alibaba/dubbo/config/spring/generic-export.xml b/dubbo-config/dubbo-config-spring/src/test/resources/com/alibaba/dubbo/config/spring/generic-export.xml new file mode 100644 index 000000000000..7126cf5d4c3a --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/test/resources/com/alibaba/dubbo/config/spring/generic-export.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-config/pom.xml b/dubbo-config/pom.xml index 2be2021cc7bb..925195632b1d 100644 --- a/dubbo-config/pom.xml +++ b/dubbo-config/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-parent - 2.4.3 + 2.8.4 dubbo-config pom diff --git a/dubbo-container/dubbo-container-api/pom.xml b/dubbo-container/dubbo-container-api/pom.xml index e819b3a79be4..3cb4bda94c49 100644 --- a/dubbo-container/dubbo-container-api/pom.xml +++ b/dubbo-container/dubbo-container-api/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-container - 2.4.3 + 2.8.4 dubbo-container-api jar @@ -37,11 +37,17 @@ org.mortbay.jetty jetty + + + org.mortbay.jetty + servlet-api + + - - org.springframework - spring - + + javax.servlet + javax.servlet-api + diff --git a/dubbo-container/dubbo-container-javaconfig/pom.xml b/dubbo-container/dubbo-container-javaconfig/pom.xml new file mode 100644 index 000000000000..3cc3985b60e1 --- /dev/null +++ b/dubbo-container/dubbo-container-javaconfig/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + com.alibaba + dubbo-container + 2.8.4 + + dubbo-container-javaconfig + jar + ${project.artifactId} + The spring container by java config module of dubbo project + + true + + + + org.springframework + spring-context + + + com.alibaba + dubbo-container-api + ${project.parent.version} + + + \ No newline at end of file diff --git a/dubbo-container/dubbo-container-javaconfig/src/main/java/com/alibaba/dubbo/container/javaconfig/JavaConfigContainer.java b/dubbo-container/dubbo-container-javaconfig/src/main/java/com/alibaba/dubbo/container/javaconfig/JavaConfigContainer.java new file mode 100644 index 000000000000..15b30a4d91f4 --- /dev/null +++ b/dubbo-container/dubbo-container-javaconfig/src/main/java/com/alibaba/dubbo/container/javaconfig/JavaConfigContainer.java @@ -0,0 +1,64 @@ +/** + * Copyright 2006-2014 handu.com. + * + * Licensed 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.container.javaconfig; + +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.container.Container; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +/** + * JavaConfigContainer. (SPI, Singleton, ThreadSafe) + * + * @author Jinkai.Ma + */ +public class JavaConfigContainer implements Container { + + private static final Logger logger = LoggerFactory.getLogger(JavaConfigContainer.class); + + public static final String SPRING_JAVACONFIG = "dubbo.spring.javaconfig"; + + public static final String DEFAULT_SPRING_JAVACONFIG = "dubbo.spring.javaconfig"; + + static AnnotationConfigApplicationContext context; + + public static AnnotationConfigApplicationContext getContext() { + return context; + } + + public void start() { + String configPath = ConfigUtils.getProperty(SPRING_JAVACONFIG); + if (configPath == null || configPath.length() == 0) { + configPath = DEFAULT_SPRING_JAVACONFIG; + } + context = new AnnotationConfigApplicationContext(configPath); + context.start(); + } + + public void stop() { + try { + if (context != null) { + context.stop(); + context.close(); + context = null; + } + } catch (Throwable e) { + logger.error(e.getMessage(), e); + } + } + +} diff --git a/dubbo-container/dubbo-container-javaconfig/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.container.Container b/dubbo-container/dubbo-container-javaconfig/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.container.Container new file mode 100644 index 000000000000..c8d7f9f4f9dc --- /dev/null +++ b/dubbo-container/dubbo-container-javaconfig/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.container.Container @@ -0,0 +1 @@ +javaconfig=com.alibaba.dubbo.container.javaconfig.JavaConfigContainer \ No newline at end of file diff --git a/dubbo-container/dubbo-container-javaconfig/src/test/java/com/alibaba/dubbo/container/javaconfig/JavaConfigContainerTest.java b/dubbo-container/dubbo-container-javaconfig/src/test/java/com/alibaba/dubbo/container/javaconfig/JavaConfigContainerTest.java new file mode 100644 index 000000000000..cdf0d50dc7b7 --- /dev/null +++ b/dubbo-container/dubbo-container-javaconfig/src/test/java/com/alibaba/dubbo/container/javaconfig/JavaConfigContainerTest.java @@ -0,0 +1,36 @@ +/** + * Copyright 2006-2014 handu.com. + * + * Licensed 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.container.javaconfig; + +import com.alibaba.dubbo.common.extension.ExtensionLoader; +import com.alibaba.dubbo.container.Container; +import org.junit.Assert; +import org.junit.Test; + +/** + * @author Jinkai.Ma + */ +public class JavaConfigContainerTest { + + @Test + public void testContainer() { + JavaConfigContainer container = (JavaConfigContainer) ExtensionLoader.getExtensionLoader(Container.class).getExtension("javaconfig"); + container.start(); + Assert.assertEquals(JavaConfigContainer.class, container.context.getBean("container").getClass()); + container.stop(); + } + +} diff --git a/dubbo-container/dubbo-container-javaconfig/src/test/java/dubbo/spring/javaconfig/TestDubboConfig.java b/dubbo-container/dubbo-container-javaconfig/src/test/java/dubbo/spring/javaconfig/TestDubboConfig.java new file mode 100644 index 000000000000..0afc4c98ce35 --- /dev/null +++ b/dubbo-container/dubbo-container-javaconfig/src/test/java/dubbo/spring/javaconfig/TestDubboConfig.java @@ -0,0 +1,33 @@ +/** + * Copyright 2006-2014 handu.com. + * + * Licensed 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 dubbo.spring.javaconfig; + +import com.alibaba.dubbo.container.javaconfig.JavaConfigContainer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author Jinkai.Ma + */ +@Configuration +public class TestDubboConfig { + + @Bean + public JavaConfigContainer container() { + return new JavaConfigContainer(); + } + +} diff --git a/dubbo-container/dubbo-container-javaconfig/src/test/resources/log4j.xml b/dubbo-container/dubbo-container-javaconfig/src/test/resources/log4j.xml new file mode 100644 index 000000000000..210b4678882c --- /dev/null +++ b/dubbo-container/dubbo-container-javaconfig/src/test/resources/log4j.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-container/dubbo-container-jetty/pom.xml b/dubbo-container/dubbo-container-jetty/pom.xml index 3f3123c50a8b..3fd180fb91a0 100644 --- a/dubbo-container/dubbo-container-jetty/pom.xml +++ b/dubbo-container/dubbo-container-jetty/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-container - 2.4.3 + 2.8.4 dubbo-container-jetty jar diff --git a/dubbo-container/dubbo-container-log4j/pom.xml b/dubbo-container/dubbo-container-log4j/pom.xml index 42bfceb8c1fc..be4637f32639 100644 --- a/dubbo-container/dubbo-container-log4j/pom.xml +++ b/dubbo-container/dubbo-container-log4j/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-container - 2.4.3 + 2.8.4 dubbo-container-log4j jar diff --git a/dubbo-container/dubbo-container-logback/pom.xml b/dubbo-container/dubbo-container-logback/pom.xml index 7b1e30188d39..a123294937e2 100644 --- a/dubbo-container/dubbo-container-logback/pom.xml +++ b/dubbo-container/dubbo-container-logback/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-container - 2.4.3 + 2.8.4 dubbo-container-logback jar diff --git a/dubbo-container/dubbo-container-spring/pom.xml b/dubbo-container/dubbo-container-spring/pom.xml index 2ff7e537dc1b..9564561a899e 100644 --- a/dubbo-container/dubbo-container-spring/pom.xml +++ b/dubbo-container/dubbo-container-spring/pom.xml @@ -1,12 +1,12 @@ - 4.0.0 - - com.alibaba - dubbo-demo - 2.4.3 - - dubbo-demo-api - jar - ${project.artifactId} - The demo module of dubbo project - - true - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + 4.0.0 + + com.alibaba + dubbo-demo + 2.8.4 + + dubbo-demo-api + jar + ${project.artifactId} + The demo module of dubbo project + + true + + + + com.alibaba + dubbo + ${project.parent.version} + + + javax.servlet + javax.servlet-api + + + javax.validation + validation-api + + + javax.ws.rs + javax.ws.rs-api + + + javax.annotation + javax.annotation-api + 1.2 + + + org.codehaus.jackson + jackson-mapper-asl + 1.9.12 + + \ No newline at end of file diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/SerializationOptimizerImpl.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/SerializationOptimizerImpl.java new file mode 100644 index 000000000000..881ba9b49b42 --- /dev/null +++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/SerializationOptimizerImpl.java @@ -0,0 +1,49 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo; + +import com.alibaba.dubbo.common.serialize.support.SerializationOptimizer; +import com.alibaba.dubbo.demo.bid.BidRequest; +import com.alibaba.dubbo.demo.bid.BidResponse; +import com.alibaba.dubbo.demo.bid.Device; +import com.alibaba.dubbo.demo.bid.Geo; +import com.alibaba.dubbo.demo.bid.Impression; +import com.alibaba.dubbo.demo.bid.SeatBid; +import com.alibaba.dubbo.demo.user.User; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +/** + * This class must be accessible from both the provider and consumer + * + * @author lishen + */ +public class SerializationOptimizerImpl implements SerializationOptimizer { + + public Collection getSerializableClasses() { + List classes = new LinkedList(); + classes.add(BidRequest.class); + classes.add(BidResponse.class); + classes.add(Device.class); + classes.add(Geo.class); + classes.add(Impression.class); + classes.add(SeatBid.class); + classes.add(User.class); + return classes; + } +} diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/bid/BidRequest.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/bid/BidRequest.java new file mode 100644 index 000000000000..905be3e4cf84 --- /dev/null +++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/bid/BidRequest.java @@ -0,0 +1,55 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.bid; + +import java.io.Serializable; +import java.util.List; + +/** + * @author lishen + */ +public class BidRequest implements Serializable { + + private String id; + + private Device device; + + private List impressions; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Device getDevice() { + return device; + } + + public void setDevice(Device device) { + this.device = device; + } + + public List getImpressions() { + return impressions; + } + + public void setImpressions(List impressions) { + this.impressions = impressions; + } +} diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/bid/BidResponse.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/bid/BidResponse.java new file mode 100644 index 000000000000..e5b26b425def --- /dev/null +++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/bid/BidResponse.java @@ -0,0 +1,44 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.bid; + +import java.io.Serializable; +import java.util.List; + +/** + * @author lishen + */ +public class BidResponse implements Serializable { + + private String id; + private List seatBids; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public List getSeatBids() { + return seatBids; + } + + public void setSeatBids(List seatBids) { + this.seatBids = seatBids; + } +} diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/bid/BidService.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/bid/BidService.java new file mode 100644 index 000000000000..31ed65d0ad45 --- /dev/null +++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/bid/BidService.java @@ -0,0 +1,23 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.bid; + +public interface BidService { + + BidResponse bid(BidRequest request); + + void throwNPE() throws NullPointerException; +} \ No newline at end of file diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/bid/Device.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/bid/Device.java new file mode 100644 index 000000000000..81dcab6960f9 --- /dev/null +++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/bid/Device.java @@ -0,0 +1,79 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.bid; + +import java.io.Serializable; + +/** + * @author lishen + */ +public class Device implements Serializable { + + private String os; + private String make; + private String version; + private String model; + private String lang; + private Geo geo; + + public String getOs() { + return os; + } + + public void setOs(String os) { + this.os = os; + } + + public String getMake() { + return make; + } + + public void setMake(String make) { + this.make = make; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + public String getLang() { + return lang; + } + + public void setLang(String lang) { + this.lang = lang; + } + + public Geo getGeo() { + return geo; + } + + public void setGeo(Geo geo) { + this.geo = geo; + } +} diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/bid/Geo.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/bid/Geo.java new file mode 100644 index 000000000000..ddbe6b2e547c --- /dev/null +++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/bid/Geo.java @@ -0,0 +1,61 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.bid; + +import java.io.Serializable; + +/** + * @author lishen + */ +public class Geo implements Serializable { + + private float lon; + private float lat; + private String country; + private String city; + + public float getLon() { + return lon; + } + + public void setLon(float lon) { + this.lon = lon; + } + + public float getLat() { + return lat; + } + + public void setLat(float lat) { + this.lat = lat; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } +} diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/bid/Impression.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/bid/Impression.java new file mode 100644 index 000000000000..2b4cddfc5594 --- /dev/null +++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/bid/Impression.java @@ -0,0 +1,43 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.bid; + +import java.io.Serializable; + +/** + * @author lishen + */ +public class Impression implements Serializable { + + private String id; + private double bidFloor; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public double getBidFloor() { + return bidFloor; + } + + public void setBidFloor(double bidFloor) { + this.bidFloor = bidFloor; + } +} diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/bid/SeatBid.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/bid/SeatBid.java new file mode 100644 index 000000000000..8e852e657b59 --- /dev/null +++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/bid/SeatBid.java @@ -0,0 +1,44 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.bid; + +import java.io.Serializable; + +/** + * @author lishen + */ +public class SeatBid implements Serializable { + + private String seat; + + private String group; + + public String getSeat() { + return seat; + } + + public void setSeat(String seat) { + this.seat = seat; + } + + public String getGroup() { + return group; + } + + public void setGroup(String group) { + this.group = group; + } +} diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/extension/ClientTraceFilter.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/extension/ClientTraceFilter.java new file mode 100644 index 000000000000..8796e71b880f --- /dev/null +++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/extension/ClientTraceFilter.java @@ -0,0 +1,36 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.extension; + +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientRequestFilter; +import javax.ws.rs.client.ClientResponseContext; +import javax.ws.rs.client.ClientResponseFilter; +import java.io.IOException; + +/** + * @author lishen + */ +public class ClientTraceFilter implements ClientRequestFilter, ClientResponseFilter { + + public void filter(ClientRequestContext requestContext) throws IOException { + System.out.println("Client request filter invoked"); + } + + public void filter(ClientRequestContext clientRequestContext, ClientResponseContext clientResponseContext) throws IOException { + System.out.println("Client response filter invoked"); + } +} diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/extension/CustomExceptionMapper.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/extension/CustomExceptionMapper.java new file mode 100644 index 000000000000..82397901ab99 --- /dev/null +++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/extension/CustomExceptionMapper.java @@ -0,0 +1,34 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.extension; + +import com.alibaba.dubbo.rpc.RpcContext; + +import javax.ws.rs.NotFoundException; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; + +/** + * @author lishen + */ +public class CustomExceptionMapper implements ExceptionMapper { + + public Response toResponse(NotFoundException e) { + System.out.println("Exception mapper successfully got an exception: " + e + ":" + e.getMessage()); + System.out.println("Client IP is " + RpcContext.getContext().getRemoteAddressString()); + return Response.status(Response.Status.NOT_FOUND).entity("Oops! the requested resource is not found!").type("text/plain").build(); + } +} diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/extension/DynamicTraceBinding.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/extension/DynamicTraceBinding.java new file mode 100644 index 000000000000..27e6521bd801 --- /dev/null +++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/extension/DynamicTraceBinding.java @@ -0,0 +1,30 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.extension; + +import javax.ws.rs.container.DynamicFeature; +import javax.ws.rs.container.ResourceInfo; +import javax.ws.rs.core.FeatureContext; + +/** + * @author lishen + */ +public class DynamicTraceBinding implements DynamicFeature { + + public void configure(ResourceInfo resourceInfo, FeatureContext context) { + context.register(DynamicTraceInterceptor.class); + } +} \ No newline at end of file diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/extension/DynamicTraceInterceptor.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/extension/DynamicTraceInterceptor.java new file mode 100644 index 000000000000..f8b8203e01ca --- /dev/null +++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/extension/DynamicTraceInterceptor.java @@ -0,0 +1,42 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.extension; + +import javax.annotation.Priority; +import javax.ws.rs.Priorities; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.ext.ReaderInterceptor; +import javax.ws.rs.ext.ReaderInterceptorContext; +import javax.ws.rs.ext.WriterInterceptor; +import javax.ws.rs.ext.WriterInterceptorContext; +import java.io.IOException; + +/** + * @author lishen + */ +@Priority(Priorities.USER) +public class DynamicTraceInterceptor implements ReaderInterceptor, WriterInterceptor { + + public Object aroundReadFrom(ReaderInterceptorContext readerInterceptorContext) throws IOException, WebApplicationException { + System.out.println("Dynamic reader interceptor invoked"); + return readerInterceptorContext.proceed(); + } + + public void aroundWriteTo(WriterInterceptorContext writerInterceptorContext) throws IOException, WebApplicationException { + System.out.println("Dynamic writer interceptor invoked"); + writerInterceptorContext.proceed(); + } +} diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/extension/TraceFilter.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/extension/TraceFilter.java new file mode 100644 index 000000000000..912770028373 --- /dev/null +++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/extension/TraceFilter.java @@ -0,0 +1,39 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.extension; + +import javax.annotation.Priority; +import javax.ws.rs.Priorities; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import java.io.IOException; + +/** + * @author lishen + */ +@Priority(Priorities.USER) +public class TraceFilter implements ContainerRequestFilter, ContainerResponseFilter { + + public void filter(ContainerRequestContext requestContext) throws IOException { + System.out.println("Request filter invoked"); + } + + public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) throws IOException { + System.out.println("Response filter invoked"); + } +} \ No newline at end of file diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/extension/TraceInterceptor.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/extension/TraceInterceptor.java new file mode 100644 index 000000000000..f8c25fc585b4 --- /dev/null +++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/extension/TraceInterceptor.java @@ -0,0 +1,42 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.extension; + +import javax.annotation.Priority; +import javax.ws.rs.Priorities; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.ext.ReaderInterceptor; +import javax.ws.rs.ext.ReaderInterceptorContext; +import javax.ws.rs.ext.WriterInterceptor; +import javax.ws.rs.ext.WriterInterceptorContext; +import java.io.IOException; + +/** + * @author lishen + */ +@Priority(Priorities.USER) +public class TraceInterceptor implements ReaderInterceptor, WriterInterceptor { + + public Object aroundReadFrom(ReaderInterceptorContext readerInterceptorContext) throws IOException, WebApplicationException { + System.out.println("Reader interceptor invoked"); + return readerInterceptorContext.proceed(); + } + + public void aroundWriteTo(WriterInterceptorContext writerInterceptorContext) throws IOException, WebApplicationException { + System.out.println("Writer interceptor invoked"); + writerInterceptorContext.proceed(); + } +} diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/hello/HelloService.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/hello/HelloService.java new file mode 100644 index 000000000000..297e7915e218 --- /dev/null +++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/hello/HelloService.java @@ -0,0 +1,23 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.hello; + +/** + * @author lishen + */ +public interface HelloService { + String hello(String name); +} diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/user/User.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/user/User.java new file mode 100644 index 000000000000..eb5a3b86f3ca --- /dev/null +++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/user/User.java @@ -0,0 +1,77 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.user; + +import org.codehaus.jackson.annotate.JsonProperty; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; + +/** + * @author lishen + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class User implements Serializable { + + @NotNull + @Min(1L) + private Long id; + + @JsonProperty("username") + @XmlElement(name = "username") + @NotNull + @Size(min = 6, max = 50) + private String name; + + public User() { + } + + public User(Long id, String name) { + this.id = id; + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return "User (" + + "id=" + id + + ", name='" + name + '\'' + + ')'; + } +} diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/user/UserService.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/user/UserService.java new file mode 100644 index 000000000000..74782f25c6e3 --- /dev/null +++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/user/UserService.java @@ -0,0 +1,25 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.user; + +/** + * @author lishen + */ +public interface UserService { + User getUser(Long id); + + Long registerUser(User user); +} diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/user/facade/AnotherUserRestService.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/user/facade/AnotherUserRestService.java new file mode 100644 index 000000000000..91ab166133ed --- /dev/null +++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/user/facade/AnotherUserRestService.java @@ -0,0 +1,30 @@ +package com.alibaba.dubbo.demo.user.facade; + +import com.alibaba.dubbo.demo.user.User; +import com.alibaba.dubbo.rpc.protocol.rest.support.ContentType; + +import javax.validation.constraints.Min; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +/** + * @author lishen + */ +@Path("u") +@Consumes({MediaType.APPLICATION_JSON, MediaType.TEXT_XML}) +@Produces({ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8}) +public interface AnotherUserRestService { + + @GET + @Path("{id : \\d+}") + User getUser(@PathParam("id") @Min(1L) Long id); + + @POST + @Path("register") + RegistrationResult registerUser(User user); +} diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/user/facade/RegistrationResult.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/user/facade/RegistrationResult.java new file mode 100644 index 000000000000..1924ed0c805c --- /dev/null +++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/user/facade/RegistrationResult.java @@ -0,0 +1,45 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.user.facade; + +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; + +/** + * DTO to customize the returned message + * + * @author lishen + */ +@XmlRootElement +public class RegistrationResult implements Serializable { + + private Long id; + + public RegistrationResult() { + } + + public RegistrationResult(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } +} diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/user/facade/UserRestService.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/user/facade/UserRestService.java new file mode 100644 index 000000000000..87f28fcd9822 --- /dev/null +++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/user/facade/UserRestService.java @@ -0,0 +1,40 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.user.facade; + +import com.alibaba.dubbo.demo.user.User; + +import javax.validation.constraints.Min; + +/** + * This interface acts as some kind of service broker for the original UserService + + * Here we want to simulate the twitter/weibo rest api, e.g. + * + * http://localhost:8888/user/1.json + * http://localhost:8888/user/1.xml + * + * @author lishen + */ +public interface UserRestService { + + /** + * the request object is just used to test jax-rs injection. + */ + User getUser(@Min(value=1L, message="User ID must be greater than 1") Long id/*, HttpServletRequest request*/); + + RegistrationResult registerUser(User user); +} diff --git a/dubbo-demo/dubbo-demo-consumer/pom.xml b/dubbo-demo/dubbo-demo-consumer/pom.xml index 2bb6838a3f63..3e2427967bb3 100644 --- a/dubbo-demo/dubbo-demo-consumer/pom.xml +++ b/dubbo-demo/dubbo-demo-consumer/pom.xml @@ -14,172 +14,220 @@ - limitations under the License. --> - 4.0.0 - - com.alibaba - dubbo-demo - 2.4.3 - - dubbo-demo-consumer - jar - ${project.artifactId} - The demo consumer module of dubbo project - - false - - - - com.alibaba - dubbo-demo-api - ${project.parent.version} - - - com.alibaba - dubbo - ${project.parent.version} - - - org.springframework - spring - - - org.javassist - javassist - - - org.jboss.netty - netty - - - org.apache.mina - mina-core - - - org.glassfish.grizzly - grizzly-core - - - org.apache.httpcomponents - httpclient - - - com.alibaba - fastjson - - - com.thoughtworks.xstream - xstream - - - org.apache.bsf - bsf-api - - - org.apache.zookeeper - zookeeper - - - com.github.sgroschupf - zkclient - - - com.netflix.curator - curator-framework - - - com.googlecode.xmemcached - xmemcached - - - org.apache.cxf - cxf-rt-frontend-simple - - - org.apache.cxf - cxf-rt-transports-http - - - org.apache.thrift - libthrift - - - com.caucho - hessian - - - javax.servlet - servlet-api - - - org.mortbay.jetty - jetty - - - log4j - log4j - - - org.slf4j - slf4j-api - - - redis.clients - jedis - - - javax.validation - validation-api - - - org.hibernate - hibernate-validator - - - javax.cache - cache-api - - - - - - maven-dependency-plugin - - - unpack - package - - unpack - - - - - com.alibaba - dubbo - ${project.parent.version} - ${project.build.directory}/dubbo - META-INF/assembly/** - - - - - - - - maven-assembly-plugin + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + 4.0.0 + + com.alibaba + dubbo-demo + 2.8.4 + + dubbo-demo-consumer + jar + ${project.artifactId} + The demo consumer module of dubbo project + + false + + + + com.alibaba + dubbo-demo-api + ${project.parent.version} + + + com.alibaba + dubbo + ${project.parent.version} + + + org.javassist + javassist + + + io.netty + netty + + + org.apache.mina + mina-core + + + org.glassfish.grizzly + grizzly-core + + + org.apache.httpcomponents + httpclient + + + com.alibaba + fastjson + + + com.thoughtworks.xstream + xstream + + + org.apache.bsf + bsf-api + + + org.apache.zookeeper + zookeeper + + + com.github.sgroschupf + zkclient + + + org.apache.curator + curator-framework + + + com.googlecode.xmemcached + xmemcached + + + org.apache.cxf + cxf-rt-frontend-simple + + + org.apache.cxf + cxf-rt-transports-http + + + org.apache.thrift + libthrift + + + com.caucho + hessian + + + javax.servlet + javax.servlet-api + + + org.mortbay.jetty + jetty + + + log4j + log4j + + + org.slf4j + slf4j-api + + + redis.clients + jedis + + + javax.validation + validation-api + + + org.hibernate + hibernate-validator + + + javax.cache + cache-api + + + + org.jboss.resteasy + resteasy-jaxrs + + + + org.jboss.resteasy + resteasy-client + + + + org.jboss.resteasy + resteasy-netty + + + + org.jboss.resteasy + resteasy-jdk-http + + + + org.jboss.resteasy + resteasy-jackson-provider + + + + org.jboss.resteasy + resteasy-jaxb-provider + + + + org.apache.tomcat.embed + tomcat-embed-core + + + org.apache.tomcat.embed + tomcat-embed-logging-juli + + + + com.esotericsoftware.kryo + kryo + + + de.javakaffee + kryo-serializers + + + de.ruedigermoeller + fst + + + + + + maven-dependency-plugin + + + unpack + package + + unpack + + + + + com.alibaba + dubbo + ${project.parent.version} + ${project.build.directory}/dubbo + META-INF/assembly/** + + + + + + + + maven-assembly-plugin src/main/assembly/assembly.xml - - make-assembly - package - - single - - - + + make-assembly + package + + single + + + - - + + \ No newline at end of file diff --git a/dubbo-demo/dubbo-demo-consumer/src/main/java/com/alibaba/dubbo/demo/consumer/DemoAction.java b/dubbo-demo/dubbo-demo-consumer/src/main/java/com/alibaba/dubbo/demo/consumer/DemoAction.java index 5258feb6e78f..b6138e729adc 100644 --- a/dubbo-demo/dubbo-demo-consumer/src/main/java/com/alibaba/dubbo/demo/consumer/DemoAction.java +++ b/dubbo-demo/dubbo-demo-consumer/src/main/java/com/alibaba/dubbo/demo/consumer/DemoAction.java @@ -15,29 +15,75 @@ */ package com.alibaba.dubbo.demo.consumer; -import java.text.SimpleDateFormat; -import java.util.Date; +import java.util.ArrayList; +import java.util.List; -import com.alibaba.dubbo.demo.DemoService; +import com.alibaba.dubbo.demo.bid.*; +import com.alibaba.dubbo.demo.user.User; +import com.alibaba.dubbo.demo.user.facade.AnotherUserRestService; +import com.alibaba.dubbo.rpc.RpcContext; public class DemoAction { - - private DemoService demoService; - public void setDemoService(DemoService demoService) { - this.demoService = demoService; + private BidService bidService; + + private AnotherUserRestService anotherUserRestService; + + public void setBidService(BidService bidService) { + this.bidService = bidService; + } + + public void setAnotherUserRestService(AnotherUserRestService anotherUserRestService) { + this.anotherUserRestService = anotherUserRestService; } - public void start() throws Exception { - for (int i = 0; i < Integer.MAX_VALUE; i ++) { - try { - String hello = demoService.sayHello("world" + i); - System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + hello); - } catch (Exception e) { - e.printStackTrace(); - } - Thread.sleep(2000); + public void start() throws Exception { + BidRequest request = new BidRequest(); + + Impression imp = new Impression(); + imp.setBidFloor(1.1); + imp.setId("abc"); + List imps = new ArrayList(1); + imps.add(imp); + request.setImpressions(imps); + + Geo geo = new Geo(); + geo.setCity("beijing"); + geo.setCountry("china"); + geo.setLat(100.1f); + geo.setLon(100.1f); + + Device device = new Device(); + device.setMake("apple"); + device.setOs("ios"); + device.setVersion("7.0"); + device.setLang("zh_CN"); + device.setModel("iphone"); + device.setGeo(geo); + request.setDevice(device); + +// long start = System.currentTimeMillis(); + +// for (int i = 0; i < 10000; i ++) { +// System.out.println(bidService.bid(request).getId()); + System.out.println("SUCCESS: got bid response id: " + bidService.bid(request).getId()); +// } + +// System.out.println(">>>>> Total time consumed:" + (System.currentTimeMillis() - start)); + + try { + bidService.throwNPE(); + System.out.println("ERROR: no exception found"); + } catch (NullPointerException e) { + System.out.println("SUCCESS: caught exception " + e.getClass()); } - } + + User user = new User(1L, "larrypage"); + System.out.println("SUCCESS: registered user with id " + anotherUserRestService.registerUser(user).getId()); + + RpcContext.getContext().setAttachment("clientName", "demo"); + RpcContext.getContext().setAttachment("clientImpl", "dubbox"); + System.out.println("SUCCESS: got user " + anotherUserRestService.getUser(1L)); + } } \ No newline at end of file diff --git a/dubbo-demo/dubbo-demo-consumer/src/main/java/com/alibaba/dubbo/demo/consumer/DemoJavaConfigAction.java b/dubbo-demo/dubbo-demo-consumer/src/main/java/com/alibaba/dubbo/demo/consumer/DemoJavaConfigAction.java new file mode 100644 index 000000000000..636aba174260 --- /dev/null +++ b/dubbo-demo/dubbo-demo-consumer/src/main/java/com/alibaba/dubbo/demo/consumer/DemoJavaConfigAction.java @@ -0,0 +1,87 @@ +/* + * Copyright 2006-2014 handu.com. + * + * Licensed 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.demo.consumer; + +import com.alibaba.dubbo.config.annotation.Reference; +import com.alibaba.dubbo.demo.bid.*; +import com.alibaba.dubbo.demo.user.User; +import com.alibaba.dubbo.demo.user.facade.AnotherUserRestService; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Jinkai.Ma + */ +@Component +public class DemoJavaConfigAction { + + @Reference + private BidService bidService; + + @Reference + private AnotherUserRestService anotherUserRestService; + + @PostConstruct + public void start() throws Exception { + BidRequest request = new BidRequest(); + + Impression imp = new Impression(); + imp.setBidFloor(1.1); + imp.setId("abc"); + List imps = new ArrayList(1); + imps.add(imp); + request.setImpressions(imps); + + Geo geo = new Geo(); + geo.setCity("beijing"); + geo.setCountry("china"); + geo.setLat(100.1f); + geo.setLon(100.1f); + + Device device = new Device(); + device.setMake("apple"); + device.setOs("ios"); + device.setVersion("7.0"); + device.setLang("zh_CN"); + device.setModel("iphone"); + device.setGeo(geo); + request.setDevice(device); + +// long start = System.currentTimeMillis(); + +// for (int i = 0; i < 10000; i ++) { +// System.out.println(bidService.bid(request).getId()); + System.out.println("SUCESS: got bid response id: " + bidService.bid(request).getId()); +// } + +// System.out.println(">>>>> Total time consumed:" + (System.currentTimeMillis() - start)); + + try { + bidService.throwNPE(); + System.out.println("ERROR: no exception found"); + } catch (NullPointerException e) { + System.out.println("SUCCESS: caught exception " + e.getClass()); + } + + User user = new User(1L, "larrypage"); + System.out.println("SUCESS: registered user with id " + anotherUserRestService.registerUser(user).getId()); + + System.out.println("SUCESS: got user " + anotherUserRestService.getUser(1L)); + } +} diff --git a/dubbo-demo/dubbo-demo-consumer/src/main/java/dubbo/spring/javaconfig/DubboDemoActionConfig.java b/dubbo-demo/dubbo-demo-consumer/src/main/java/dubbo/spring/javaconfig/DubboDemoActionConfig.java new file mode 100644 index 000000000000..ea27c4039236 --- /dev/null +++ b/dubbo-demo/dubbo-demo-consumer/src/main/java/dubbo/spring/javaconfig/DubboDemoActionConfig.java @@ -0,0 +1,33 @@ +/* + * Copyright 2006-2014 handu.com. + * + * Licensed 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 dubbo.spring.javaconfig; + +import com.alibaba.dubbo.demo.consumer.DemoJavaConfigAction; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author Jinkai.Ma + */ +@Configuration +public class DubboDemoActionConfig { + + @Bean + public DemoJavaConfigAction demoAnnotationAction() { + return new DemoJavaConfigAction(); + } + +} diff --git a/dubbo-demo/dubbo-demo-consumer/src/main/java/dubbo/spring/javaconfig/DubboDemoConsumerConfig.java b/dubbo-demo/dubbo-demo-consumer/src/main/java/dubbo/spring/javaconfig/DubboDemoConsumerConfig.java new file mode 100644 index 000000000000..2052150a92fb --- /dev/null +++ b/dubbo-demo/dubbo-demo-consumer/src/main/java/dubbo/spring/javaconfig/DubboDemoConsumerConfig.java @@ -0,0 +1,56 @@ +/* + * Copyright 2006-2014 handu.com. + * + * Licensed 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 dubbo.spring.javaconfig; + +import com.alibaba.dubbo.config.ApplicationConfig; +import com.alibaba.dubbo.config.RegistryConfig; +import com.alibaba.dubbo.config.spring.AnnotationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author Jinkai.Ma + */ +@Configuration +public class DubboDemoConsumerConfig { + + public static final String APPLICATION_NAME = "consumer-of-helloworld-app"; + + public static final String REGISTRY_ADDRESS = "zookeeper://127.0.0.1:2181"; + + public static final String ANNOTATION_PACKAGE = "com.alibaba.dubbo.demo.consumer"; + + @Bean + public ApplicationConfig applicationConfig() { + ApplicationConfig applicationConfig = new ApplicationConfig(); + applicationConfig.setName(APPLICATION_NAME); + return applicationConfig; + } + + @Bean + public RegistryConfig registryConfig() { + RegistryConfig registryConfig = new RegistryConfig(); + registryConfig.setAddress(REGISTRY_ADDRESS); + return registryConfig; + } + + @Bean + public AnnotationBean annotationBean() { + AnnotationBean annotationBean = new AnnotationBean(); + annotationBean.setPackage(ANNOTATION_PACKAGE); + return annotationBean; + } +} diff --git a/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-action.xml b/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-action.xml index 365bafb80a67..fb7662ca0002 100644 --- a/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-action.xml +++ b/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-action.xml @@ -20,8 +20,9 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> - - + + + \ No newline at end of file diff --git a/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml b/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml index 981599fb175d..6dd555c68f92 100644 --- a/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml +++ b/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml @@ -1,25 +1,21 @@ - - + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-demo/dubbo-demo-consumer/src/test/java/com/alibaba/dubbo/demo/consumer/DemoJavaConfigConsumer.java b/dubbo-demo/dubbo-demo-consumer/src/test/java/com/alibaba/dubbo/demo/consumer/DemoJavaConfigConsumer.java new file mode 100644 index 000000000000..afbe0704394b --- /dev/null +++ b/dubbo-demo/dubbo-demo-consumer/src/test/java/com/alibaba/dubbo/demo/consumer/DemoJavaConfigConsumer.java @@ -0,0 +1,27 @@ +/* + * Copyright 2006-2014 handu.com. + * + * Licensed 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.demo.consumer; + +/** + * @author Jinkai.Ma + */ +public class DemoJavaConfigConsumer { + public static void main(String[] args) { + // add `javaconfig` to args + String[] customArgs = new String[]{"javaconfig"}; + com.alibaba.dubbo.container.Main.main(customArgs); + } +} diff --git a/dubbo-demo/dubbo-demo-consumer/src/test/java/com/alibaba/dubbo/demo/consumer/RestClient.java b/dubbo-demo/dubbo-demo-consumer/src/test/java/com/alibaba/dubbo/demo/consumer/RestClient.java new file mode 100644 index 000000000000..b8fd5fddba81 --- /dev/null +++ b/dubbo-demo/dubbo-demo-consumer/src/test/java/com/alibaba/dubbo/demo/consumer/RestClient.java @@ -0,0 +1,104 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.consumer; + +import com.alibaba.dubbo.demo.user.User; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +/** + * @author lishen + */ +public class RestClient { + + public static void main(String[] args) { + final String port = "8888"; +// final String port = "8080"; + +// for (int i = 0; i < 500; i++) { +// final int index = i + 1; +// new Thread(new Runnable() { +// public void run() { +// System.out.println("Starting thread " + index + "..."); +// for (int j = 0; j < 500; j++) { + registerUser("http://localhost:" + port + "/services/users/register.json", MediaType.APPLICATION_JSON_TYPE); + + registerUser("http://localhost:" + port + "/services/users/register.xml", MediaType.TEXT_XML_TYPE); + + getUser("http://localhost:" + port + "/services/users/1.json"); + + getUser("http://localhost:" + port + "/services/users/2.xml"); + + registerUser("http://localhost:" + port + "/services/u/register.json", MediaType.APPLICATION_JSON_TYPE); + + registerUser("http://localhost:" + port + "/services/u/register.xml", MediaType.TEXT_XML_TYPE); + + getUser("http://localhost:" + port + "/services/u/1.json"); + + getUser("http://localhost:" + port + "/services/u/2.xml"); + + registerUser("http://localhost:" + port + "/services/customers/register.json", MediaType.APPLICATION_JSON_TYPE); + + registerUser("http://localhost:" + port + "/services/customers/register.xml", MediaType.TEXT_XML_TYPE); + + getUser("http://localhost:" + port + "/services/customers/1.json"); + + getUser("http://localhost:" + port + "/services/customers/2.xml"); +// } +// } +// }).start(); +// } + } + + private static void registerUser(String url, MediaType mediaType) { + System.out.println("Registering user via " + url); + User user = new User(1L, "larrypage"); + Client client = ClientBuilder.newClient(); + WebTarget target = client.target(url); + Response response = target.request().post(Entity.entity(user, mediaType)); + + try { + if (response.getStatus() != 200) { + throw new RuntimeException("Failed with HTTP error code : " + response.getStatus()); + } + System.out.println("Successfully got result: " + response.readEntity(String.class)); + } finally { + response.close(); + client.close(); + } + } + + private static void getUser(String url) { + System.out.println("Getting user via " + url); + Client client = ClientBuilder.newClient(); + WebTarget target = client.target(url); + Response response = target.request().get(); + try { + if (response.getStatus() != 200) { + throw new RuntimeException("Failed with HTTP error code : " + response.getStatus()); + } + System.out.println("Successfully got result: " + response.readEntity(String.class)); + } finally { + response.close(); + client.close(); + } + } +} diff --git a/dubbo-demo/dubbo-demo-provider/pom.xml b/dubbo-demo/dubbo-demo-provider/pom.xml index 9fce8bc5b86f..1d6192f7aec7 100644 --- a/dubbo-demo/dubbo-demo-provider/pom.xml +++ b/dubbo-demo/dubbo-demo-provider/pom.xml @@ -14,172 +14,226 @@ - limitations under the License. --> - 4.0.0 - - com.alibaba - dubbo-demo - 2.4.3 - - dubbo-demo-provider - jar - ${project.artifactId} - The demo provider module of dubbo project - - false - - - - com.alibaba - dubbo-demo-api - ${project.parent.version} - - - com.alibaba - dubbo - ${project.parent.version} - - - org.springframework - spring - - - org.javassist - javassist - - - org.jboss.netty - netty - - - org.apache.mina - mina-core - - - org.glassfish.grizzly - grizzly-core - - - org.apache.httpcomponents - httpclient - - - com.alibaba - fastjson - - - com.thoughtworks.xstream - xstream - - - org.apache.bsf - bsf-api - - - org.apache.zookeeper - zookeeper - - - com.github.sgroschupf - zkclient - - - com.netflix.curator - curator-framework - - - com.googlecode.xmemcached - xmemcached - - - org.apache.cxf - cxf-rt-frontend-simple - - - org.apache.cxf - cxf-rt-transports-http - - - org.apache.thrift - libthrift - - - com.caucho - hessian - - - javax.servlet - servlet-api - - - org.mortbay.jetty - jetty - - - log4j - log4j - - - org.slf4j - slf4j-api - - - redis.clients - jedis - - - javax.validation - validation-api - - - org.hibernate - hibernate-validator - - - javax.cache - cache-api - - - - - - maven-dependency-plugin - - - unpack - package - - unpack - - - - - com.alibaba - dubbo - ${project.parent.version} - ${project.build.directory}/dubbo - META-INF/assembly/** - - - - - - - - maven-assembly-plugin - - src/main/assembly/assembly.xml - - - - make-assembly - package - - single - - - - - - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + 4.0.0 + + com.alibaba + dubbo-demo + 2.8.4 + + dubbo-demo-provider + war + ${project.artifactId} + The demo provider module of dubbo project + + false + + + + com.alibaba + dubbo-demo-api + ${project.parent.version} + + + com.alibaba + dubbo + ${project.parent.version} + + + org.javassist + javassist + + + io.netty + netty + + + org.apache.mina + mina-core + + + org.glassfish.grizzly + grizzly-core + + + org.apache.httpcomponents + httpclient + + + com.alibaba + fastjson + + + com.thoughtworks.xstream + xstream + + + org.apache.bsf + bsf-api + + + org.apache.zookeeper + zookeeper + + + com.github.sgroschupf + zkclient + + + org.apache.curator + curator-framework + + + com.googlecode.xmemcached + xmemcached + + + org.apache.cxf + cxf-rt-frontend-simple + + + org.apache.cxf + cxf-rt-transports-http + + + org.apache.thrift + libthrift + + + com.caucho + hessian + + + javax.servlet + javax.servlet-api + + + org.mortbay.jetty + jetty + + + org.mortbay.jetty + servlet-api + + + + + log4j + log4j + + + org.slf4j + slf4j-api + + + redis.clients + jedis + + + javax.validation + validation-api + + + org.hibernate + hibernate-validator + + + javax.cache + cache-api + + + + org.jboss.resteasy + resteasy-jaxrs + + + + org.jboss.resteasy + resteasy-client + + + + org.jboss.resteasy + resteasy-netty + + + + org.jboss.resteasy + resteasy-jdk-http + + + + org.jboss.resteasy + resteasy-jackson-provider + + + + org.jboss.resteasy + resteasy-jaxb-provider + + + + org.apache.tomcat.embed + tomcat-embed-core + + + org.apache.tomcat.embed + tomcat-embed-logging-juli + + + + com.esotericsoftware.kryo + kryo + + + de.javakaffee + kryo-serializers + + + de.ruedigermoeller + fst + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-demo/dubbo-demo-provider/src/main/assembly/conf/dubbo.properties b/dubbo-demo/dubbo-demo-provider/src/main/assembly/conf/dubbo.properties deleted file mode 100644 index 728be32db500..000000000000 --- a/dubbo-demo/dubbo-demo-provider/src/main/assembly/conf/dubbo.properties +++ /dev/null @@ -1,28 +0,0 @@ -## -# Copyright 1999-2011 Alibaba Group. -# -# Licensed 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. -## -dubbo.container=log4j,spring -dubbo.application.name=demo-provider -dubbo.application.owner= -dubbo.registry.address=multicast://224.5.6.7:1234 -#dubbo.registry.address=zookeeper://127.0.0.1:2181 -#dubbo.registry.address=redis://127.0.0.1:6379 -#dubbo.registry.address=dubbo://127.0.0.1:9090 -dubbo.monitor.protocol=registry -dubbo.protocol.name=dubbo -dubbo.protocol.port=20880 -dubbo.service.loadbalance=roundrobin -dubbo.log4j.file=logs/dubbo-demo-provider.log -dubbo.log4j.level=WARN \ No newline at end of file diff --git a/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/bid/BidServiceImpl.java b/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/bid/BidServiceImpl.java new file mode 100644 index 000000000000..391ffbc3a810 --- /dev/null +++ b/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/bid/BidServiceImpl.java @@ -0,0 +1,43 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.bid; + +import java.util.ArrayList; +import java.util.List; + +public class BidServiceImpl implements BidService { + + public BidResponse bid(BidRequest request) { + BidResponse response = new BidResponse(); + + response.setId("abc"); + + SeatBid seatBid = new SeatBid(); + seatBid.setGroup("group"); + seatBid.setSeat("seat"); + List seatBids = new ArrayList(1); + seatBids.add(seatBid); + + response.setSeatBids(seatBids); + + return response; + } + + public void throwNPE() throws NullPointerException { + throw new NullPointerException(); + } + +} \ No newline at end of file diff --git a/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/hello/HelloServiceImpl.java b/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/hello/HelloServiceImpl.java new file mode 100644 index 000000000000..80fcf24fc566 --- /dev/null +++ b/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/hello/HelloServiceImpl.java @@ -0,0 +1,26 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.hello; + +/** + * @author lishen + */ +public class HelloServiceImpl implements HelloService { + + public String hello(String name) { + return "hello " + name; + } +} diff --git a/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/DemoServiceImpl.java b/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/DemoServiceImpl.java deleted file mode 100644 index 346ab601fb0f..000000000000 --- a/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/DemoServiceImpl.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 1999-2011 Alibaba Group. - * - * Licensed 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.demo.provider; - -import java.text.SimpleDateFormat; -import java.util.Date; - -import com.alibaba.dubbo.demo.DemoService; -import com.alibaba.dubbo.rpc.RpcContext; - -public class DemoServiceImpl implements DemoService { - - public String sayHello(String name) { - System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress()); - return "Hello " + name + ", response form provider: " + RpcContext.getContext().getLocalAddress(); - } - -} \ No newline at end of file diff --git a/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/user/UserServiceImpl.java b/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/user/UserServiceImpl.java new file mode 100644 index 000000000000..e722a01573f2 --- /dev/null +++ b/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/user/UserServiceImpl.java @@ -0,0 +1,36 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.user; + +import java.util.concurrent.atomic.AtomicLong; + +/** + * @author lishen + */ +public class UserServiceImpl implements UserService { + + private final AtomicLong idGen = new AtomicLong(); + + public User getUser(Long id) { + return new User(id, "username" + id); + } + + + public Long registerUser(User user) { +// System.out.println("Username is " + user.getName()); + return idGen.incrementAndGet(); + } +} diff --git a/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/user/facade/AnnotationDrivenUserRestServiceImpl.java b/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/user/facade/AnnotationDrivenUserRestServiceImpl.java new file mode 100644 index 000000000000..e7dd278dacd3 --- /dev/null +++ b/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/user/facade/AnnotationDrivenUserRestServiceImpl.java @@ -0,0 +1,64 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.user.facade; + +import com.alibaba.dubbo.config.annotation.Service; +import com.alibaba.dubbo.demo.user.User; +import com.alibaba.dubbo.demo.user.UserService; +import com.alibaba.dubbo.rpc.protocol.rest.support.ContentType; +import org.springframework.beans.factory.annotation.Autowired; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +/** + * @author lishen + */ +@Service(protocol = {"rest", "dubbo"}, group = "annotationConfig", validation = "true") +@Path("customers") +@Consumes({MediaType.APPLICATION_JSON, MediaType.TEXT_XML}) +@Produces({ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8}) +public class AnnotationDrivenUserRestServiceImpl implements UserRestService { + +// private static final Logger logger = LoggerFactory.getLogger(UserRestServiceImpl.class); + + @Autowired + private UserService userService; + + public void setUserService(UserService userService) { + this.userService = userService; + } + + @GET + @Path("{id : \\d+}") + public User getUser(@PathParam("id") Long id/*, @Context HttpServletRequest request*/) { + // test context injection +// System.out.println("Client address from @Context injection: " + (request != null ? request.getRemoteAddr() : "")); +// System.out.println("Client address from RpcContext: " + RpcContext.getContext().getRemoteAddressString()); + return userService.getUser(id); + } + + @POST + @Path("register") + public RegistrationResult registerUser(User user) { + return new RegistrationResult(userService.registerUser(user)); + } +} diff --git a/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/user/facade/AnotherUserRestServiceImpl.java b/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/user/facade/AnotherUserRestServiceImpl.java new file mode 100644 index 000000000000..23a1ba282e23 --- /dev/null +++ b/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/user/facade/AnotherUserRestServiceImpl.java @@ -0,0 +1,42 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.user.facade; + +import com.alibaba.dubbo.demo.user.User; +import com.alibaba.dubbo.demo.user.UserService; +import com.alibaba.dubbo.rpc.RpcContext; + +/** + * @author lishen + */ +public class AnotherUserRestServiceImpl implements AnotherUserRestService { + + private UserService userService; + + public void setUserService(UserService userService) { + this.userService = userService; + } + + public User getUser(Long id) { + System.out.println("Client name is " + RpcContext.getContext().getAttachment("clientName")); + System.out.println("Client impl is " + RpcContext.getContext().getAttachment("clientImpl")); + return userService.getUser(id); + } + + public RegistrationResult registerUser(User user) { + return new RegistrationResult(userService.registerUser(user)); + } +} diff --git a/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/user/facade/UserRestServiceImpl.java b/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/user/facade/UserRestServiceImpl.java new file mode 100644 index 000000000000..659a82035108 --- /dev/null +++ b/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/user/facade/UserRestServiceImpl.java @@ -0,0 +1,71 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demo.user.facade; + +import com.alibaba.dubbo.demo.user.User; +import com.alibaba.dubbo.demo.user.UserService; +import com.alibaba.dubbo.demo.user.facade.RegistrationResult; +import com.alibaba.dubbo.demo.user.facade.UserRestService; +import com.alibaba.dubbo.rpc.RpcContext; +import com.alibaba.dubbo.rpc.protocol.rest.support.ContentType; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +/** + * @author lishen + */ +@Path("users") +@Consumes({MediaType.APPLICATION_JSON, MediaType.TEXT_XML}) +@Produces({ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8}) +public class UserRestServiceImpl implements UserRestService { + +// private static final Logger logger = LoggerFactory.getLogger(UserRestServiceImpl.class); + + private UserService userService; + + public void setUserService(UserService userService) { + this.userService = userService; + } + + @GET + @Path("{id : \\d+}") + public User getUser(@PathParam("id") Long id/*, @Context HttpServletRequest request*/) { + // test context injection +// System.out.println("Client address from @Context injection: " + (request != null ? request.getRemoteAddr() : "")); +// System.out.println("Client address from RpcContext: " + RpcContext.getContext().getRemoteAddressString()); + if (RpcContext.getContext().getRequest(HttpServletRequest.class) != null) { + System.out.println("Client IP address from RpcContext: " + RpcContext.getContext().getRequest(HttpServletRequest.class).getRemoteAddr()); + } + if (RpcContext.getContext().getResponse(HttpServletResponse.class) != null) { + System.out.println("Response object from RpcContext: " + RpcContext.getContext().getResponse(HttpServletResponse.class)); + } + return userService.getUser(id); + } + + @POST + @Path("register") + public RegistrationResult registerUser(User user) { + return new RegistrationResult(userService.registerUser(user)); + } +} diff --git a/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml b/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml index ea8026b6ed86..265645ab00ba 100644 --- a/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml +++ b/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml @@ -19,9 +19,66 @@ xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-demo/dubbo-demo-provider/src/test/resources/log4j.xml b/dubbo-demo/dubbo-demo-provider/src/main/resources/log4j.xml similarity index 97% rename from dubbo-demo/dubbo-demo-provider/src/test/resources/log4j.xml rename to dubbo-demo/dubbo-demo-provider/src/main/resources/log4j.xml index 7d7163464096..ae988c35f139 100644 --- a/dubbo-demo/dubbo-demo-provider/src/test/resources/log4j.xml +++ b/dubbo-demo/dubbo-demo-provider/src/main/resources/log4j.xml @@ -1,28 +1,28 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-demo/dubbo-demo-provider/src/main/webapp/WEB-INF/web.xml b/dubbo-demo/dubbo-demo-provider/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000000..9a355c15ffce --- /dev/null +++ b/dubbo-demo/dubbo-demo-provider/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,30 @@ + + + + + + contextConfigLocation + /WEB-INF/classes/META-INF/spring/dubbo-demo-provider.xml + + + + + com.alibaba.dubbo.remoting.http.servlet.BootstrapListener + + + + org.springframework.web.context.ContextLoaderListener + + + + dispatcher + com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet + 1 + + + + dispatcher + /services/* + + \ No newline at end of file diff --git a/dubbo-demo/dubbo-demo-provider/src/test/java/com/alibaba/dubbo/demo/provider/DemoProvider.java b/dubbo-demo/dubbo-demo-provider/src/test/java/com/alibaba/dubbo/demo/provider/DemoProvider.java index 31850ef4bfcc..b00688c9efc3 100644 --- a/dubbo-demo/dubbo-demo-provider/src/test/java/com/alibaba/dubbo/demo/provider/DemoProvider.java +++ b/dubbo-demo/dubbo-demo-provider/src/test/java/com/alibaba/dubbo/demo/provider/DemoProvider.java @@ -15,10 +15,22 @@ */ package com.alibaba.dubbo.demo.provider; +import com.alibaba.dubbo.config.ProtocolConfig; + public class DemoProvider { public static void main(String[] args) { +// new Thread(new Runnable() { +// public void run() { +// try { +// Thread.sleep(20000); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// ProtocolConfig.destroyAll(); +// } +// }).start(); com.alibaba.dubbo.container.Main.main(args); - } + } } \ No newline at end of file diff --git a/dubbo-demo/dubbo-demo-provider/src/test/resources/dubbo.properties b/dubbo-demo/dubbo-demo-provider/src/test/resources/dubbo.properties deleted file mode 100644 index 600d6089adc1..000000000000 --- a/dubbo-demo/dubbo-demo-provider/src/test/resources/dubbo.properties +++ /dev/null @@ -1,28 +0,0 @@ -## -# Copyright 1999-2011 Alibaba Group. -# -# Licensed 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. -## -dubbo.container=log4j,spring -dubbo.application.name=demo-provider -dubbo.application.owner=william -dubbo.registry.address=multicast://224.5.6.7:1234 -#dubbo.registry.address=zookeeper://127.0.0.1:2181 -#dubbo.registry.address=redis://127.0.0.1:6379 -#dubbo.registry.address=dubbo://127.0.0.1:9090 -#dubbo.monitor.protocol=registry -dubbo.protocol.name=dubbo -dubbo.protocol.port=20880 -dubbo.service.loadbalance=roundrobin -#dubbo.log4j.file=logs/dubbo-demo-consumer.log -#dubbo.log4j.level=WARN \ No newline at end of file diff --git a/dubbo-demo/pom.xml b/dubbo-demo/pom.xml index ffe6a8d6fe88..4d77e14ec9ab 100644 --- a/dubbo-demo/pom.xml +++ b/dubbo-demo/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-parent - 2.4.3 + 2.8.4 dubbo-demo pom diff --git a/dubbo-filter/dubbo-filter-cache/pom.xml b/dubbo-filter/dubbo-filter-cache/pom.xml index 9fd371f46c11..8431bef623d6 100644 --- a/dubbo-filter/dubbo-filter-cache/pom.xml +++ b/dubbo-filter/dubbo-filter-cache/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-filter - 2.4.3 + 2.8.4 dubbo-filter-cache jar diff --git a/dubbo-filter/dubbo-filter-validation/pom.xml b/dubbo-filter/dubbo-filter-validation/pom.xml index 1036e0e66a79..d3d9cc121344 100644 --- a/dubbo-filter/dubbo-filter-validation/pom.xml +++ b/dubbo-filter/dubbo-filter-validation/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-filter - 2.4.3 + 2.8.4 dubbo-filter-validation jar diff --git a/dubbo-filter/dubbo-filter-validation/src/main/java/com/alibaba/dubbo/validation/support/jvalidation/JValidator.java b/dubbo-filter/dubbo-filter-validation/src/main/java/com/alibaba/dubbo/validation/support/jvalidation/JValidator.java index 1c84bd17fb80..ab5a3cce3ab0 100644 --- a/dubbo-filter/dubbo-filter-validation/src/main/java/com/alibaba/dubbo/validation/support/jvalidation/JValidator.java +++ b/dubbo-filter/dubbo-filter-validation/src/main/java/com/alibaba/dubbo/validation/support/jvalidation/JValidator.java @@ -157,7 +157,7 @@ private static Object getMethodParameterBean(Class clazz, Method method, Obje try { String upperName = toUpperMethoName(method.getName()); String parameterSimpleName = upperName + "Parameter"; - String parameterClassName = clazz.getName() + "$" + parameterSimpleName; + String parameterClassName = clazz.getName() + "_" + parameterSimpleName; Class parameterClass; try { parameterClass = (Class) Class.forName(parameterClassName, true, clazz.getClassLoader()); diff --git a/dubbo-filter/pom.xml b/dubbo-filter/pom.xml index d2021aa6959f..86e2ef12fbf7 100644 --- a/dubbo-filter/pom.xml +++ b/dubbo-filter/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-parent - 2.4.3 + 2.8.4 dubbo-filter pom diff --git a/dubbo-maven/pom.xml b/dubbo-maven/pom.xml new file mode 100644 index 000000000000..68893fdf6c63 --- /dev/null +++ b/dubbo-maven/pom.xml @@ -0,0 +1,354 @@ + + + 4.0.0 + + org.sonatype.oss + oss-parent + 7 + + com.alibaba + dubbo + 2.4.3 + jar + Dubbo + Dubbo is a distributed service framework enpowers applications with service import/export capability with high performance RPC. + http://code.alibabatech.com/wiki/display/dubbo + 2012 + + + Apache 2 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + A business-friendly OSS license + + + + Alibaba + http://www.alibaba.com + + + + org.springframework + spring + 2.5.6.SEC03 + + + org.javassist + javassist + 3.15.0-GA + + + io.netty + netty + 3.2.5.Final + + + org.apache.mina + mina-core + 1.1.7 + provided + + + org.glassfish.grizzly + grizzly-core + 2.1.4 + provided + + + org.apache.httpcomponents + httpclient + 4.1.2 + provided + + + com.alibaba + fastjson + 1.1.18 + provided + + + com.thoughtworks.xstream + xstream + 1.4.1 + provided + + + org.apache.bsf + bsf-api + 3.1 + provided + + + org.apache.zookeeper + zookeeper + 3.3.3 + provided + + + com.github.sgroschupf + zkclient + 0.1 + provided + + + com.netflix.curator + curator-framework + 1.1.10 + provided + + + com.googlecode.xmemcached + xmemcached + 1.3.6 + provided + + + org.apache.cxf + cxf-rt-frontend-simple + 2.6.1 + provided + + + org.apache.cxf + cxf-rt-transports-http + 2.6.1 + provided + + + org.apache.thrift + libthrift + 0.8.0 + provided + + + com.caucho + hessian + 4.0.7 + provided + + + javax.servlet + javax.servlet-api + 2.5 + provided + + + org.mortbay.jetty + jetty + 6.1.26 + provided + + + log4j + log4j + 1.2.16 + provided + + + org.slf4j + slf4j-api + 1.6.2 + provided + + + redis.clients + jedis + 2.0.0 + provided + + + javax.validation + validation-api + 1.0.0.GA + provided + + + org.hibernate + hibernate-validator + 4.2.0.Final + provided + + + javax.cache + cache-api + 0.4 + provided + + + ch.qos.logback + logback-classic + 1.0.6 + provided + + + + + + maven-source-plugin + + + attach-sources + + jar + + + + + + maven-compiler-plugin + + 1.5 + 1.5 + UTF-8 + + + + maven-jar-plugin + + + true + true + + true + true + + + + + + maven-javadoc-plugin + + + attach-javadoc + + jar + + + + + public + UTF-8 + UTF-8 + UTF-8 + com.alibaba.com.* + + http://docs.oracle.com/javase/6/docs/api + + + + + maven-gpg-plugin + + + sign-artifacts + verify + + sign + + + + + + + + true + + + jira + http://code.alibabatech.com/jira/browse/DUBBO + + + http://code.alibabatech.com/svn/dubbo/trunk + scm:svn:http://code.alibabatech.com/svn/dubbo/trunk + scm:svn:http://code.alibabatech.com/svn/dubbo/trunk + + + + Dubbo User Mailling List + dubbo-subscribe AT googlegroups DOT com + dubbo-unsubscribe AT googlegroups DOT com + dubbo AT googlegroups DOT com + http://groups.google.com/group/dubbo + + + + + QianXiao(Shawn) + shawn.qianx + shawn.qianx (AT) alibaba-inc.com + + Developer + + +8 + + + LiangFei(William) + william.liangf + william.liangf (AT) alibaba-inc.com + + Developer + + +8 + + + LiDing(Jerry) + ding.lid + ding.lid (AT) alibaba-inc.com + + Developer + + +8 + + + LiuChao(Charles) + chao.liuc + chao.liuc (AT) alibaba-inc.com + + Developer + + +8 + + + LiuHaoMin(Ludvik) + haoming.liuhm + haoming.liuhm (AT) alibaba-inc.com + + Developer + + +8 + + + ChenLei(Tony) + tony.chenl + tony.chenl (AT) alibaba-inc.com + + Developer + + +8 + + + LuGang(Kimi) + gang.lvgm + gang.lvgm (AT) alibaba-inc.com + + Developer + + +8 + + + diff --git a/dubbo-monitor/dubbo-monitor-api/pom.xml b/dubbo-monitor/dubbo-monitor-api/pom.xml index bff67cbfaee9..e654f038a54f 100644 --- a/dubbo-monitor/dubbo-monitor-api/pom.xml +++ b/dubbo-monitor/dubbo-monitor-api/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-monitor - 2.4.3 + 2.8.4 dubbo-monitor-api jar diff --git a/dubbo-monitor/dubbo-monitor-default/pom.xml b/dubbo-monitor/dubbo-monitor-default/pom.xml index 5628348a26b4..957fda3e4228 100644 --- a/dubbo-monitor/dubbo-monitor-default/pom.xml +++ b/dubbo-monitor/dubbo-monitor-default/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-monitor - 2.4.3 + 2.8.4 dubbo-monitor-default jar diff --git a/dubbo-monitor/pom.xml b/dubbo-monitor/pom.xml index 6f20eff64676..5061c3f56065 100644 --- a/dubbo-monitor/pom.xml +++ b/dubbo-monitor/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-parent - 2.4.3 + 2.8.4 dubbo-monitor pom diff --git a/dubbo-registry/dubbo-registry-api/pom.xml b/dubbo-registry/dubbo-registry-api/pom.xml index a9ed6d76695f..25572a8b656d 100644 --- a/dubbo-registry/dubbo-registry-api/pom.xml +++ b/dubbo-registry/dubbo-registry-api/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-registry - 2.4.3 + 2.8.4 dubbo-registry-api jar diff --git a/dubbo-registry/dubbo-registry-default/pom.xml b/dubbo-registry/dubbo-registry-default/pom.xml index 6acaba5dc5b3..2ee2515bed91 100644 --- a/dubbo-registry/dubbo-registry-default/pom.xml +++ b/dubbo-registry/dubbo-registry-default/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-registry - 2.4.3 + 2.8.4 dubbo-registry-default jar diff --git a/dubbo-registry/dubbo-registry-default/src/test/java/com/alibaba/dubbo/registry/dubbo/RegistryDirectoryTest.java b/dubbo-registry/dubbo-registry-default/src/test/java/com/alibaba/dubbo/registry/dubbo/RegistryDirectoryTest.java index cca1ab8020a2..58f5aed00594 100644 --- a/dubbo-registry/dubbo-registry-default/src/test/java/com/alibaba/dubbo/registry/dubbo/RegistryDirectoryTest.java +++ b/dubbo-registry/dubbo-registry-default/src/test/java/com/alibaba/dubbo/registry/dubbo/RegistryDirectoryTest.java @@ -550,12 +550,12 @@ public void testNotifyRouterUrls() { List routers = registryDirectory.getRouters(); //default invocation selector Assert.assertEquals(1+1, routers.size()); - Assert.assertEquals(ScriptRouter.class, routers.get(0).getClass()); + Assert.assertEquals(ScriptRouter.class, routers.get(1).getClass()); registryDirectory.notify(new ArrayList()); routers = registryDirectory.getRouters(); Assert.assertEquals(1 + 1, routers.size()); - Assert.assertEquals(ScriptRouter.class, routers.get(0).getClass()); + Assert.assertEquals(ScriptRouter.class, routers.get(1).getClass()); serviceUrls.clear(); serviceUrls.add(routerurl.addParameter(Constants.ROUTER_KEY, Constants.ROUTER_TYPE_CLEAR)); diff --git a/dubbo-registry/dubbo-registry-multicast/pom.xml b/dubbo-registry/dubbo-registry-multicast/pom.xml index 531ece4dc6ab..478d4fb67b7a 100644 --- a/dubbo-registry/dubbo-registry-multicast/pom.xml +++ b/dubbo-registry/dubbo-registry-multicast/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-registry - 2.4.3 + 2.8.4 dubbo-registry-multicast jar diff --git a/dubbo-registry/dubbo-registry-redis/pom.xml b/dubbo-registry/dubbo-registry-redis/pom.xml index 3d6470c99f22..10c9fa26b499 100644 --- a/dubbo-registry/dubbo-registry-redis/pom.xml +++ b/dubbo-registry/dubbo-registry-redis/pom.xml @@ -1,12 +1,12 @@ - - 4.0.0 - - com.alibaba - dubbo-parent - 2.4.3 - - dubbo-remoting - pom - ${project.artifactId} - The remoting module of dubbo project - - true - - - dubbo-remoting-api - dubbo-remoting-netty - dubbo-remoting-mina - dubbo-remoting-grizzly - dubbo-remoting-p2p - dubbo-remoting-http - dubbo-remoting-zookeeper - - + + + 4.0.0 + + com.alibaba + dubbo-parent + 2.8.4 + + dubbo-remoting + pom + ${project.artifactId} + The remoting module of dubbo project + + true + + + dubbo-remoting-api + dubbo-remoting-netty + dubbo-remoting-mina + dubbo-remoting-grizzly + dubbo-remoting-p2p + dubbo-remoting-http + dubbo-remoting-zookeeper + + \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-api/pom.xml b/dubbo-rpc/dubbo-rpc-api/pom.xml index c1deb1f6b317..e713642d38e9 100644 --- a/dubbo-rpc/dubbo-rpc-api/pom.xml +++ b/dubbo-rpc/dubbo-rpc-api/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-rpc - 2.4.3 + 2.8.4 dubbo-rpc-api jar 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 25a34f4b6204..e0d6cd752366 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 @@ -89,7 +89,12 @@ public static void removeContext() { private final Map attachments = new HashMap(); private final Map values = new HashMap(); - + + // now we don't use the 'values' map to hold these objects + // we want these objects to be as generic as possible + private Object request; + private Object response; + @Deprecated private List> invokers; @@ -102,6 +107,53 @@ public static void removeContext() { protected RpcContext() { } + /** + * Get the request object of the underlying RPC protocol, e.g. HttpServletRequest + * + * @return null if the underlying protocol doesn't provide support for getting request + */ + public Object getRequest() { + return request; + } + + /** + * Get the request object of the underlying RPC protocol, e.g. HttpServletRequest + * + * @return null if the underlying protocol doesn't provide support for getting request or the request is not of the specified type + */ + @SuppressWarnings("unchecked") + public T getRequest(Class clazz) { + return (request != null && clazz.isAssignableFrom(request.getClass())) ? (T) request : null; + } + + + public void setRequest(Object request) { + this.request = request; + } + + /** + * Get the response object of the underlying RPC protocol, e.g. HttpServletResponse + * + * @return null if the underlying protocol doesn't provide support for getting response + */ + public Object getResponse() { + return response; + } + + /** + * Get the response object of the underlying RPC protocol, e.g. HttpServletResponse + * + * @return null if the underlying protocol doesn't provide support for getting response or the response is not of the specified type + */ + @SuppressWarnings("unchecked") + public T getResponse(Class clazz) { + return (response != null && clazz.isAssignableFrom(response.getClass())) ? (T) response : null; + } + + public void setResponse(Object response) { + this.response = response; + } + /** * is provider side. * diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/ServiceClassHolder.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/ServiceClassHolder.java new file mode 100644 index 000000000000..e6f9ec151652 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/ServiceClassHolder.java @@ -0,0 +1,30 @@ +package com.alibaba.dubbo.rpc; + +/** + * TODO this is just a workround for rest protocol, and now we just ensure it works in the most common dubbo usages + * + * @author lishen + */ +public class ServiceClassHolder { + + private static final ServiceClassHolder INSTANCE = new ServiceClassHolder(); + + private final ThreadLocal holder = new ThreadLocal(); + + public static ServiceClassHolder getInstance() { + return INSTANCE; + } + + private ServiceClassHolder() { + } + + public Class popServiceClass() { + Class clazz = holder.get(); + holder.remove(); + return clazz; + } + + public void pushServiceClass(Class clazz) { + holder.set(clazz); + } +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/AccessLogFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/AccessLogFilter.java index 49e4ce9635de..2ed19aaf316b 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/AccessLogFilter.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/AccessLogFilter.java @@ -1,47 +1,48 @@ -/* - * Copyright 1999-2011 Alibaba Group. - * - * Licensed 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. - */ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.filter; -import java.io.File; -import java.io.FileWriter; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -import com.alibaba.dubbo.common.Constants; -import com.alibaba.dubbo.common.extension.Activate; -import com.alibaba.dubbo.common.json.JSON; -import com.alibaba.dubbo.common.logger.Logger; -import com.alibaba.dubbo.common.logger.LoggerFactory; -import com.alibaba.dubbo.common.utils.ConcurrentHashSet; -import com.alibaba.dubbo.common.utils.ConfigUtils; -import com.alibaba.dubbo.common.utils.NamedThreadFactory; -import com.alibaba.dubbo.rpc.Filter; -import com.alibaba.dubbo.rpc.Invocation; -import com.alibaba.dubbo.rpc.Invoker; -import com.alibaba.dubbo.rpc.Result; -import com.alibaba.dubbo.rpc.RpcContext; -import com.alibaba.dubbo.rpc.RpcException; +import java.io.File; +import java.io.FileWriter; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import com.alibaba.dubbo.common.Constants; +import com.alibaba.dubbo.common.extension.Activate; +import com.alibaba.dubbo.common.json.JSON; +import com.alibaba.dubbo.common.logger.Logger; +import com.alibaba.dubbo.common.logger.LoggerFactory; +import com.alibaba.dubbo.common.utils.ConcurrentHashSet; +import com.alibaba.dubbo.common.utils.ConfigUtils; +import com.alibaba.dubbo.common.utils.NamedThreadFactory; +import com.alibaba.dubbo.rpc.Filter; +import com.alibaba.dubbo.rpc.Invocation; +import com.alibaba.dubbo.rpc.Invoker; +import com.alibaba.dubbo.rpc.Result; +import com.alibaba.dubbo.rpc.RpcContext; +import com.alibaba.dubbo.rpc.RpcException; /** * 记录Service的Access Log。 @@ -57,7 +58,7 @@ * * * @author ding.lid - */ + */ @Activate(group = Constants.PROVIDER, value = Constants.ACCESS_LOG_KEY) public class AccessLogFilter implements Filter { @@ -105,15 +106,16 @@ public void run() { } FileWriter writer = new FileWriter(file, true); try { - for (String msg : logSet) { - writer.write(msg); + for(Iterator iterator = logSet.iterator(); + iterator.hasNext(); + iterator.remove()) { + writer.write(iterator.next()); writer.write("\r\n"); } writer.flush(); } finally { writer.close(); } - logSet.clear(); } catch (Exception e) { logger.error(e.getMessage(), e); } 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 f3736907a05a..4097697ecfbe 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 @@ -50,9 +50,19 @@ public Result invoke(Invoker invoker, Invocation invocation) throws RpcExcept RpcContext.getContext() .setInvoker(invoker) .setInvocation(invocation) - .setAttachments(attachments) - .setLocalAddress(invoker.getUrl().getHost(), - invoker.getUrl().getPort()); +// .setAttachments(attachments) // modified by lishen + .setLocalAddress(invoker.getUrl().getHost(), + invoker.getUrl().getPort()); + + // modified by lishen + if (attachments != null) { + if (RpcContext.getContext().getAttachments() != null) { + RpcContext.getContext().getAttachments().putAll(attachments); + } else { + RpcContext.getContext().setAttachments(attachments); + } + } + if (invocation instanceof RpcInvocation) { ((RpcInvocation)invocation).setInvoker(invoker); } diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/GenericFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/GenericFilter.java index b2aedb048cc0..efd324197f45 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/GenericFilter.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/GenericFilter.java @@ -19,6 +19,9 @@ import java.lang.reflect.Method; import com.alibaba.dubbo.common.Constants; +import com.alibaba.dubbo.common.beanutil.JavaBeanAccessor; +import com.alibaba.dubbo.common.beanutil.JavaBeanDescriptor; +import com.alibaba.dubbo.common.beanutil.JavaBeanSerializeUtil; import com.alibaba.dubbo.common.extension.Activate; import com.alibaba.dubbo.common.extension.ExtensionLoader; import com.alibaba.dubbo.common.io.UnsafeByteArrayInputStream; @@ -49,7 +52,7 @@ public Result invoke(Invoker invoker, Invocation inv) throws RpcException { if (inv.getMethodName().equals(Constants.$INVOKE) && inv.getArguments() != null && inv.getArguments().length == 3 - && ! invoker.getUrl().getParameter(Constants.GENERIC_KEY, false)) { + && ! ProtocolUtils.isGeneric(invoker.getUrl().getParameter(Constants.GENERIC_KEY))) { String name = ((String) inv.getArguments()[0]).trim(); String[] types = (String[]) inv.getArguments()[1]; Object[] args = (Object[]) inv.getArguments()[2]; @@ -84,6 +87,21 @@ public Result invoke(Invoker invoker, Invocation inv) throws RpcException { .append(args[i].getClass()).toString()); } } + } else if (ProtocolUtils.isBeanGenericSerialization(generic)) { + for(int i = 0; i < args.length; i++) { + if (args[i] instanceof JavaBeanDescriptor) { + args[i] = JavaBeanSerializeUtil.deserialize((JavaBeanDescriptor)args[i]); + } else { + throw new RpcException( + new StringBuilder(32) + .append("Generic serialization [") + .append(Constants.GENERIC_SERIALIZATION_BEAN) + .append("] only support message type ") + .append(JavaBeanDescriptor.class.getName()) + .append(" and your message type is ") + .append(args[i].getClass().getName()).toString()); + } + } } Result result = invoker.invoke(new RpcInvocation(method, args, inv.getAttachments())); if (result.hasException() @@ -100,6 +118,8 @@ public Result invoke(Invoker invoker, Invocation inv) throws RpcException { } catch (IOException e) { throw new RpcException("Serialize result failed.", e); } + } else if (ProtocolUtils.isBeanGenericSerialization(generic)) { + return new RpcResult(JavaBeanSerializeUtil.serialize(result.getValue(), JavaBeanAccessor.METHOD)); } else { return new RpcResult(PojoUtils.generalize(result.getValue())); } diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/GenericImplFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/GenericImplFilter.java index 44015dba5a95..31df520c2d1d 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/GenericImplFilter.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/GenericImplFilter.java @@ -20,6 +20,9 @@ import java.lang.reflect.Method; import com.alibaba.dubbo.common.Constants; +import com.alibaba.dubbo.common.beanutil.JavaBeanAccessor; +import com.alibaba.dubbo.common.beanutil.JavaBeanDescriptor; +import com.alibaba.dubbo.common.beanutil.JavaBeanSerializeUtil; import com.alibaba.dubbo.common.extension.Activate; import com.alibaba.dubbo.common.logger.Logger; import com.alibaba.dubbo.common.logger.LoggerFactory; @@ -61,7 +64,16 @@ public Result invoke(Invoker invoker, Invocation invocation) throws RpcExcept for (int i = 0; i < parameterTypes.length; i ++) { types[i] = ReflectUtils.getName(parameterTypes[i]); } - Object[] args = PojoUtils.generalize(arguments); + + Object[] args; + if (ProtocolUtils.isBeanGenericSerialization(generic)) { + args = new Object[arguments.length]; + for(int i = 0; i < arguments.length; i++) { + args[i] = JavaBeanSerializeUtil.serialize(arguments[i], JavaBeanAccessor.METHOD); + } + } else { + args = PojoUtils.generalize(arguments); + } invocation2.setMethodName(Constants.$INVOKE); invocation2.setParameterTypes(GENERIC_PARAMETER_TYPES); @@ -72,7 +84,24 @@ public Result invoke(Invoker invoker, Invocation invocation) throws RpcExcept Object value = result.getValue(); try { Method method = invoker.getInterface().getMethod(methodName, parameterTypes); - return new RpcResult(PojoUtils.realize(value, method.getReturnType(), method.getGenericReturnType())); + if (ProtocolUtils.isBeanGenericSerialization(generic)) { + if (value == null) { + return new RpcResult(value); + } else if (value instanceof JavaBeanDescriptor) { + return new RpcResult(JavaBeanSerializeUtil.deserialize((JavaBeanDescriptor)value)); + } else { + throw new RpcException( + new StringBuilder(64) + .append("The type of result value is ") + .append(value.getClass().getName()) + .append(" other than ") + .append(JavaBeanDescriptor.class.getName()) + .append(", and the result is ") + .append(value).toString()); + } + } else { + return new RpcResult(PojoUtils.realize(value, method.getReturnType(), method.getGenericReturnType())); + } } catch (NoSuchMethodException e) { throw new RpcException(e.getMessage(), e); } @@ -122,12 +151,18 @@ public Result invoke(Invoker invoker, Invocation invocation) throws RpcExcept && invocation.getArguments().length == 3 && ProtocolUtils.isGeneric(generic)) { + Object[] args = (Object[]) invocation.getArguments()[2]; if (ProtocolUtils.isJavaGenericSerialization(generic)) { - Object[] args = (Object[]) invocation.getArguments()[2]; for (Object arg : args) { if (!(byte[].class == arg.getClass())) { - error(arg.getClass().getName()); + error(byte[].class.getName(), arg.getClass().getName()); + } + } + } else if (ProtocolUtils.isBeanGenericSerialization(generic)) { + for(Object arg : args) { + if (!(arg instanceof JavaBeanDescriptor)) { + error(JavaBeanDescriptor.class.getName(), arg.getClass().getName()); } } } @@ -138,15 +173,15 @@ public Result invoke(Invoker invoker, Invocation invocation) throws RpcExcept return invoker.invoke(invocation); } - private void error(String type) throws RpcException { + private void error(String expected, String actual) throws RpcException { throw new RpcException( new StringBuilder(32) .append("Generic serialization [") .append(Constants.GENERIC_SERIALIZATION_NATIVE_JAVA) .append("] only support message type ") - .append(byte[].class) + .append(expected) .append(" and your message type is ") - .append(type).toString()); + .append(actual).toString()); } } \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/support/ProtocolUtils.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/support/ProtocolUtils.java index f0440f02c029..837af632da87 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/support/ProtocolUtils.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/support/ProtocolUtils.java @@ -36,7 +36,8 @@ public static boolean isGeneric(String generic) { return generic != null && !"".equals(generic) && (Constants.GENERIC_SERIALIZATION_DEFAULT.equalsIgnoreCase(generic) /* 正常的泛化调用 */ - || Constants.GENERIC_SERIALIZATION_NATIVE_JAVA.equalsIgnoreCase(generic)); /* 支持java序列化的流式泛化调用 */ + || Constants.GENERIC_SERIALIZATION_NATIVE_JAVA.equalsIgnoreCase(generic) /* 支持java序列化的流式泛化调用 */ + || Constants.GENERIC_SERIALIZATION_BEAN.equalsIgnoreCase(generic)); } public static boolean isDefaultGenericSerialization(String generic) { @@ -48,4 +49,8 @@ public static boolean isJavaGenericSerialization(String generic) { return isGeneric(generic) && Constants.GENERIC_SERIALIZATION_NATIVE_JAVA.equalsIgnoreCase(generic); } + + public static boolean isBeanGenericSerialization(String generic) { + return isGeneric(generic) && Constants.GENERIC_SERIALIZATION_BEAN.equals(generic); + } } diff --git a/dubbo-rpc/dubbo-rpc-default/pom.xml b/dubbo-rpc/dubbo-rpc-default/pom.xml index 2e09d214fc7d..a31250d37dbf 100644 --- a/dubbo-rpc/dubbo-rpc-default/pom.xml +++ b/dubbo-rpc/dubbo-rpc-default/pom.xml @@ -1,65 +1,71 @@ - - - 4.0.0 - - com.alibaba - dubbo-rpc - 2.4.3 - - dubbo-rpc-default - jar - ${project.artifactId} - The default rpc module of dubbo project - - true - - - - com.alibaba - dubbo-rpc-api - ${project.parent.version} - - - com.alibaba - dubbo-remoting-api - ${project.parent.version} - - - com.alibaba - dubbo-container-api - ${project.parent.version} - - - org.mortbay.jetty - jetty - - - - - com.alibaba - dubbo-remoting-netty - ${project.parent.version} - test - - - org.apache.mina - mina-core - test - - + + + 4.0.0 + + com.alibaba + dubbo-rpc + 2.8.4 + + dubbo-rpc-default + jar + ${project.artifactId} + The default rpc module of dubbo project + + true + + + + com.alibaba + dubbo-rpc-api + ${project.parent.version} + + + com.alibaba + dubbo-remoting-api + ${project.parent.version} + + + com.alibaba + dubbo-container-api + ${project.parent.version} + + + org.mortbay.jetty + jetty + + + + + com.alibaba + dubbo-remoting-netty + ${project.parent.version} + test + + + com.alibaba + dubbo-remoting-mina + ${project.parent.version} + test + + + org.apache.mina + mina-core + test + + \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-default/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java b/dubbo-rpc/dubbo-rpc-default/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java index 7ca3b9f5d90d..8c1e46759c4c 100644 --- a/dubbo-rpc/dubbo-rpc-default/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java +++ b/dubbo-rpc/dubbo-rpc-default/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java @@ -25,7 +25,10 @@ import com.alibaba.dubbo.common.Constants; import com.alibaba.dubbo.common.logger.Logger; import com.alibaba.dubbo.common.logger.LoggerFactory; +import com.alibaba.dubbo.common.serialize.Cleanable; import com.alibaba.dubbo.common.serialize.ObjectInput; +import com.alibaba.dubbo.common.serialize.OptimizedSerialization; +import com.alibaba.dubbo.common.serialize.support.kryo.KryoSerialization; import com.alibaba.dubbo.common.utils.Assert; import com.alibaba.dubbo.common.utils.ReflectUtils; import com.alibaba.dubbo.common.utils.StringUtils; @@ -87,53 +90,83 @@ public void encode(Channel channel, OutputStream output, Object message) throws public Object decode(Channel channel, InputStream input) throws IOException { ObjectInput in = CodecSupport.getSerialization(channel.getUrl(), serializationType) - .deserialize(channel.getUrl(), input); + .deserialize(channel.getUrl(), input); - setAttachment(Constants.DUBBO_VERSION_KEY, in.readUTF()); - setAttachment(Constants.PATH_KEY, in.readUTF()); - setAttachment(Constants.VERSION_KEY, in.readUTF()); - - setMethodName(in.readUTF()); try { - Object[] args; - Class[] pts; - String desc = in.readUTF(); - if (desc.length() == 0) { - pts = DubboCodec.EMPTY_CLASS_ARRAY; - args = DubboCodec.EMPTY_OBJECT_ARRAY; - } else { - pts = ReflectUtils.desc2classArray(desc); - args = new Object[pts.length]; - for (int i = 0; i < args.length; i++) { - try { - args[i] = in.readObject(pts[i]); - } catch (Exception e) { - if (log.isWarnEnabled()) { - log.warn("Decode argument failed: " + e.getMessage(), e); + setAttachment(Constants.DUBBO_VERSION_KEY, in.readUTF()); + setAttachment(Constants.PATH_KEY, in.readUTF()); + setAttachment(Constants.VERSION_KEY, in.readUTF()); + + setMethodName(in.readUTF()); + try { + Object[] args; + Class[] pts; + + // NOTICE modified by lishen + int argNum = in.readInt(); + if (argNum >= 0) { + if (argNum == 0) { + pts = DubboCodec.EMPTY_CLASS_ARRAY; + args = DubboCodec.EMPTY_OBJECT_ARRAY; + } else { + args = new Object[argNum]; + pts = new Class[argNum]; + for (int i = 0; i < args.length; i++) { + try { + args[i] = in.readObject(); + pts[i] = args[i].getClass(); + } catch (Exception e) { + if (log.isWarnEnabled()) { + log.warn("Decode argument failed: " + e.getMessage(), e); + } + } + } + } + } else { + String desc = in.readUTF(); + if (desc.length() == 0) { + pts = DubboCodec.EMPTY_CLASS_ARRAY; + args = DubboCodec.EMPTY_OBJECT_ARRAY; + } else { + pts = ReflectUtils.desc2classArray(desc); + args = new Object[pts.length]; + for (int i = 0; i < args.length; i++) { + try { + args[i] = in.readObject(pts[i]); + } catch (Exception e) { + if (log.isWarnEnabled()) { + log.warn("Decode argument failed: " + e.getMessage(), e); + } + } } } } - } - setParameterTypes(pts); + setParameterTypes(pts); - Map map = (Map) in.readObject(Map.class); - if (map != null && map.size() > 0) { - Map attachment = getAttachments(); - if (attachment == null) { - attachment = new HashMap(); + Map map = (Map) in.readObject(Map.class); + if (map != null && map.size() > 0) { + Map attachment = getAttachments(); + if (attachment == null) { + attachment = new HashMap(); + } + attachment.putAll(map); + setAttachments(attachment); + } + //decode argument ,may be callback + for (int i = 0; i < args.length; i++) { + args[i] = decodeInvocationArgument(channel, this, pts, i, args[i]); } - attachment.putAll(map); - setAttachments(attachment); - } - //decode argument ,may be callback - for (int i = 0; i < args.length; i++) { - args[i] = decodeInvocationArgument(channel, this, pts, i, args[i]); - } - setArguments(args); + setArguments(args); - } catch (ClassNotFoundException e) { - throw new IOException(StringUtils.toString("Read invocation data failed.", e)); + } catch (ClassNotFoundException e) { + throw new IOException(StringUtils.toString("Read invocation data failed.", e)); + } + } finally { + // modified by lishen + if (in instanceof Cleanable) { + ((Cleanable) in).cleanup(); + } } return this; } diff --git a/dubbo-rpc/dubbo-rpc-default/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java b/dubbo-rpc/dubbo-rpc-default/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java index 27dd08029f09..6c1d0b46be3b 100644 --- a/dubbo-rpc/dubbo-rpc-default/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java +++ b/dubbo-rpc/dubbo-rpc-default/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java @@ -23,6 +23,7 @@ import com.alibaba.dubbo.common.logger.Logger; import com.alibaba.dubbo.common.logger.LoggerFactory; +import com.alibaba.dubbo.common.serialize.Cleanable; import com.alibaba.dubbo.common.serialize.ObjectInput; import com.alibaba.dubbo.common.utils.Assert; import com.alibaba.dubbo.common.utils.StringUtils; @@ -73,34 +74,41 @@ public Object decode(Channel channel, InputStream input) throws IOException { ObjectInput in = CodecSupport.getSerialization(channel.getUrl(), serializationType) .deserialize(channel.getUrl(), input); - byte flag = in.readByte(); - switch (flag) { - case DubboCodec.RESPONSE_NULL_VALUE: - break; - case DubboCodec.RESPONSE_VALUE: - 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]))); - } catch (ClassNotFoundException e) { - throw new IOException(StringUtils.toString("Read response data failed.", e)); - } - break; - case DubboCodec.RESPONSE_WITH_EXCEPTION: - try { - Object obj = in.readObject(); - if (obj instanceof Throwable == false) - throw new IOException("Response data error, expect Throwable, but get " + obj); - setException((Throwable) obj); - } 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); + try { + byte flag = in.readByte(); + switch (flag) { + case DubboCodec.RESPONSE_NULL_VALUE: + break; + case DubboCodec.RESPONSE_VALUE: + 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]))); + } catch (ClassNotFoundException e) { + throw new IOException(StringUtils.toString("Read response data failed.", e)); + } + break; + case DubboCodec.RESPONSE_WITH_EXCEPTION: + try { + Object obj = in.readObject(); + if (obj instanceof Throwable == false) + throw new IOException("Response data error, expect Throwable, but get " + obj); + setException((Throwable) obj); + } 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); + } + return this; + } finally { + // modified by lishen + if (in instanceof Cleanable) { + ((Cleanable) in).cleanup(); + } } - return this; } public void decode() throws Exception { diff --git a/dubbo-rpc/dubbo-rpc-default/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboCodec.java b/dubbo-rpc/dubbo-rpc-default/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboCodec.java index 6a003d3c1c62..3e5fd8944f14 100644 --- a/dubbo-rpc/dubbo-rpc-default/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboCodec.java +++ b/dubbo-rpc/dubbo-rpc-default/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboCodec.java @@ -27,11 +27,12 @@ import com.alibaba.dubbo.common.logger.LoggerFactory; import com.alibaba.dubbo.common.serialize.ObjectInput; import com.alibaba.dubbo.common.serialize.ObjectOutput; +import com.alibaba.dubbo.common.serialize.OptimizedSerialization; import com.alibaba.dubbo.common.serialize.Serialization; import com.alibaba.dubbo.common.utils.ReflectUtils; import com.alibaba.dubbo.common.utils.StringUtils; import com.alibaba.dubbo.remoting.Channel; -import com.alibaba.dubbo.remoting.Codec; +import com.alibaba.dubbo.remoting.Codec2; import com.alibaba.dubbo.remoting.exchange.Request; import com.alibaba.dubbo.remoting.exchange.Response; import com.alibaba.dubbo.remoting.exchange.codec.ExchangeCodec; @@ -48,7 +49,7 @@ * @author qianlei * @author chao.liuc */ -public class DubboCodec extends ExchangeCodec implements Codec { +public class DubboCodec extends ExchangeCodec implements Codec2 { private static final Logger log = LoggerFactory.getLogger(DubboCodec.class); @@ -90,15 +91,15 @@ protected Object decodeBody(Channel channel, InputStream is, byte[] header) thro } else { DecodeableRpcResult result; if (channel.getUrl().getParameter( - Constants.DECODE_IN_IO_THREAD_KEY, - Constants.DEFAULT_DECODE_IN_IO_THREAD)) { + Constants.DECODE_IN_IO_THREAD_KEY, + Constants.DEFAULT_DECODE_IN_IO_THREAD)) { result = new DecodeableRpcResult(channel, res, is, - (Invocation)getRequestData(id), proto); + (Invocation)getRequestData(id), proto); result.decode(); } else { result = new DecodeableRpcResult(channel, res, - new UnsafeByteArrayInputStream(readMessageData(is)), - (Invocation) getRequestData(id), proto); + new UnsafeByteArrayInputStream(readMessageData(is)), + (Invocation) getRequestData(id), proto); } data = result; } @@ -131,13 +132,13 @@ protected Object decodeBody(Channel channel, InputStream is, byte[] header) thro } else { DecodeableRpcInvocation inv; if (channel.getUrl().getParameter( - Constants.DECODE_IN_IO_THREAD_KEY, - Constants.DEFAULT_DECODE_IN_IO_THREAD)) { + Constants.DECODE_IN_IO_THREAD_KEY, + Constants.DEFAULT_DECODE_IN_IO_THREAD)) { inv = new DecodeableRpcInvocation(channel, req, is, proto); inv.decode(); } else { inv = new DecodeableRpcInvocation(channel, req, - new UnsafeByteArrayInputStream(readMessageData(is)), proto); + new UnsafeByteArrayInputStream(readMessageData(is)), proto); } data = inv; } @@ -155,7 +156,7 @@ protected Object decodeBody(Channel channel, InputStream is, byte[] header) thro } private ObjectInput deserialize(Serialization serialization, URL url, InputStream is) - throws IOException { + throws IOException { return serialization.deserialize(url, is); } @@ -177,12 +178,21 @@ protected void encodeRequestData(Channel channel, ObjectOutput out, Object data) out.writeUTF(inv.getAttachment(Constants.VERSION_KEY)); out.writeUTF(inv.getMethodName()); - out.writeUTF(ReflectUtils.getDesc(inv.getParameterTypes())); + + // NOTICE modified by lishen + // TODO + if (getSerialization(channel) instanceof OptimizedSerialization && !containComplexArguments(inv)) { + out.writeInt(inv.getParameterTypes().length); + } else { + out.writeInt(-1); + out.writeUTF(ReflectUtils.getDesc(inv.getParameterTypes())); + } + Object[] args = inv.getArguments(); if (args != null) - for (int i = 0; i < args.length; i++){ - out.writeObject(encodeInvocationArgument(channel, inv, i)); - } + for (int i = 0; i < args.length; i++){ + out.writeObject(encodeInvocationArgument(channel, inv, i)); + } out.writeObject(inv.getAttachments()); } @@ -204,4 +214,14 @@ protected void encodeResponseData(Channel channel, ObjectOutput out, Object data out.writeObject(th); } } + + // workaround for the target method matching of kryo & fst + private boolean containComplexArguments(RpcInvocation invocation) { + for (int i = 0; i < invocation.getParameterTypes().length; i++) { + if (invocation.getArguments()[i] == null || invocation.getParameterTypes()[i] != invocation.getArguments()[i].getClass()) { + return true; + } + } + return false; + } } \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-default/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboCountCodec.java b/dubbo-rpc/dubbo-rpc-default/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboCountCodec.java index 42e08f352421..9c6b02cf2360 100644 --- a/dubbo-rpc/dubbo-rpc-default/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboCountCodec.java +++ b/dubbo-rpc/dubbo-rpc-default/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboCountCodec.java @@ -17,48 +17,44 @@ package com.alibaba.dubbo.rpc.protocol.dubbo; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; import com.alibaba.dubbo.common.Constants; -import com.alibaba.dubbo.common.io.UnsafeByteArrayInputStream; import com.alibaba.dubbo.remoting.Channel; -import com.alibaba.dubbo.remoting.Codec; +import com.alibaba.dubbo.remoting.Codec2; +import com.alibaba.dubbo.remoting.buffer.ChannelBuffer; import com.alibaba.dubbo.remoting.exchange.Request; import com.alibaba.dubbo.remoting.exchange.Response; +import com.alibaba.dubbo.remoting.exchange.support.MultiMessage; import com.alibaba.dubbo.rpc.RpcInvocation; import com.alibaba.dubbo.rpc.RpcResult; /** * @author kimi */ -public final class DubboCountCodec implements Codec { +public final class DubboCountCodec implements Codec2 { private DubboCodec codec = new DubboCodec(); - public void encode(Channel channel, OutputStream output, Object msg) throws IOException { - codec.encode(channel, output, msg); + public void encode(Channel channel, ChannelBuffer buffer, Object msg) throws IOException { + codec.encode(channel, buffer, msg); } - public Object decode(Channel channel, InputStream input) throws IOException { - UnsafeByteArrayInputStream bis = (UnsafeByteArrayInputStream)input; - int save = bis.position(); - List result = new ArrayList(); + public Object decode(Channel channel, ChannelBuffer buffer) throws IOException { + int save = buffer.readerIndex(); + MultiMessage result = MultiMessage.create(); do { - Object obj = codec.decode(channel, bis); - if (NEED_MORE_INPUT == obj) { - bis.position(save); + Object obj = codec.decode(channel, buffer); + if (Codec2.DecodeResult.NEED_MORE_INPUT == obj) { + buffer.readerIndex(save); break; } else { - result.add(obj); - logMessageLength(obj, bis.position() - save); - save = bis.position(); + result.addMessage(obj); + logMessageLength(obj, buffer.readerIndex() - save); + save = buffer.readerIndex(); } } while (true); if (result.isEmpty()) { - return NEED_MORE_INPUT; + return Codec2.DecodeResult.NEED_MORE_INPUT; } if (result.size() == 1) { return result.get(0); diff --git a/dubbo-rpc/dubbo-rpc-default/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboProtocol.java b/dubbo-rpc/dubbo-rpc-default/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboProtocol.java index 30f49f88a225..b90cd1274db1 100644 --- a/dubbo-rpc/dubbo-rpc-default/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboProtocol.java +++ b/dubbo-rpc/dubbo-rpc-default/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboProtocol.java @@ -1,53 +1,56 @@ -/* - * Copyright 1999-2011 Alibaba Group. - * - * Licensed 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. - */ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.dubbo; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.locks.ReentrantLock; - -import com.alibaba.dubbo.common.Constants; -import com.alibaba.dubbo.common.URL; -import com.alibaba.dubbo.common.Version; -import com.alibaba.dubbo.common.extension.ExtensionLoader; -import com.alibaba.dubbo.common.utils.NetUtils; -import com.alibaba.dubbo.common.utils.StringUtils; -import com.alibaba.dubbo.remoting.Channel; -import com.alibaba.dubbo.remoting.RemotingException; -import com.alibaba.dubbo.remoting.Transporter; -import com.alibaba.dubbo.remoting.exchange.ExchangeChannel; -import com.alibaba.dubbo.remoting.exchange.ExchangeClient; -import com.alibaba.dubbo.remoting.exchange.ExchangeHandler; -import com.alibaba.dubbo.remoting.exchange.ExchangeServer; -import com.alibaba.dubbo.remoting.exchange.Exchangers; -import com.alibaba.dubbo.remoting.exchange.support.ExchangeHandlerAdapter; -import com.alibaba.dubbo.rpc.Exporter; -import com.alibaba.dubbo.rpc.Invocation; -import com.alibaba.dubbo.rpc.Invoker; -import com.alibaba.dubbo.rpc.Protocol; -import com.alibaba.dubbo.rpc.RpcContext; -import com.alibaba.dubbo.rpc.RpcException; -import com.alibaba.dubbo.rpc.RpcInvocation; -import com.alibaba.dubbo.rpc.protocol.AbstractProtocol; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.locks.ReentrantLock; + +import com.alibaba.dubbo.common.Constants; +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.Version; +import com.alibaba.dubbo.common.extension.ExtensionLoader; +import com.alibaba.dubbo.common.serialize.support.SerializableClassRegistry; +import com.alibaba.dubbo.common.serialize.support.SerializationOptimizer; +import com.alibaba.dubbo.common.utils.ConcurrentHashSet; +import com.alibaba.dubbo.common.utils.NetUtils; +import com.alibaba.dubbo.common.utils.StringUtils; +import com.alibaba.dubbo.remoting.Channel; +import com.alibaba.dubbo.remoting.RemotingException; +import com.alibaba.dubbo.remoting.Transporter; +import com.alibaba.dubbo.remoting.exchange.ExchangeChannel; +import com.alibaba.dubbo.remoting.exchange.ExchangeClient; +import com.alibaba.dubbo.remoting.exchange.ExchangeHandler; +import com.alibaba.dubbo.remoting.exchange.ExchangeServer; +import com.alibaba.dubbo.remoting.exchange.Exchangers; +import com.alibaba.dubbo.remoting.exchange.support.ExchangeHandlerAdapter; +import com.alibaba.dubbo.rpc.Exporter; +import com.alibaba.dubbo.rpc.Invocation; +import com.alibaba.dubbo.rpc.Invoker; +import com.alibaba.dubbo.rpc.Protocol; +import com.alibaba.dubbo.rpc.RpcContext; +import com.alibaba.dubbo.rpc.RpcException; +import com.alibaba.dubbo.rpc.RpcInvocation; +import com.alibaba.dubbo.rpc.protocol.AbstractProtocol; /** * dubbo protocol support. @@ -62,20 +65,22 @@ public class DubboProtocol extends AbstractProtocol { public static final String COMPATIBLE_CODEC_NAME = "dubbo1compatible"; - public static final int DEFAULT_PORT = 20880; - + public static final int DEFAULT_PORT = 20880; + public final ReentrantLock lock = new ReentrantLock(); - private final Map serverMap = new ConcurrentHashMap(); // - - private final Map referenceClientMap = new ConcurrentHashMap(); // - - private final ConcurrentMap ghostClientMap = new ConcurrentHashMap(); + private final Map serverMap = new ConcurrentHashMap(); // + + private final Map referenceClientMap = new ConcurrentHashMap(); // + private final ConcurrentMap ghostClientMap = new ConcurrentHashMap(); + + private final Set optimizers = new ConcurrentHashSet(); + //consumer side export a stub service for dispatching event //servicekey-stubmethods - private final ConcurrentMap stubServiceMethodsMap = new ConcurrentHashMap(); - + private final ConcurrentMap stubServiceMethodsMap = new ConcurrentHashMap(); + private static final String IS_CALLBACK_SERVICE_INVOKE = "_isCallBackServiceInvoke"; private ExchangeHandler requestHandler = new ExchangeHandlerAdapter() { @@ -179,46 +184,46 @@ public Collection getServers() { public Collection> getExporters() { return Collections.unmodifiableCollection(exporterMap.values()); - } - - Map> getExporterMap(){ - return exporterMap; - } - - private boolean isClientSide(Channel channel) { - InetSocketAddress address = channel.getRemoteAddress(); - URL url = channel.getUrl(); - return url.getPort() == address.getPort() && - NetUtils.filterLocalHost(channel.getUrl().getIp()) - .equals(NetUtils.filterLocalHost(address.getAddress().getHostAddress())); - } - - Invoker getInvoker(Channel channel, Invocation inv) throws RemotingException{ - boolean isCallBackServiceInvoke = false; - boolean isStubServiceInvoke = false; - int port = channel.getLocalAddress().getPort(); - String path = inv.getAttachments().get(Constants.PATH_KEY); - //如果是客户端的回调服务. - isStubServiceInvoke = Boolean.TRUE.toString().equals(inv.getAttachments().get(Constants.STUB_EVENT_KEY)); - if (isStubServiceInvoke){ - port = channel.getRemoteAddress().getPort(); - } - //callback - isCallBackServiceInvoke = isClientSide(channel) && !isStubServiceInvoke; - if(isCallBackServiceInvoke){ - path = inv.getAttachments().get(Constants.PATH_KEY)+"."+inv.getAttachments().get(Constants.CALLBACK_SERVICE_KEY); - inv.getAttachments().put(IS_CALLBACK_SERVICE_INVOKE, Boolean.TRUE.toString()); - } - String serviceKey = serviceKey(port, path, inv.getAttachments().get(Constants.VERSION_KEY), inv.getAttachments().get(Constants.GROUP_KEY)); - - DubboExporter exporter = (DubboExporter) exporterMap.get(serviceKey); - - if (exporter == null) - throw new RemotingException(channel, "Not found exported service: " + serviceKey + " in " + exporterMap.keySet() + ", may be version or group mismatch " + ", channel: consumer: " + channel.getRemoteAddress() + " --> provider: " + channel.getLocalAddress() + ", message:" + inv); - - return exporter.getInvoker(); - } - + } + + Map> getExporterMap(){ + return exporterMap; + } + + private boolean isClientSide(Channel channel) { + InetSocketAddress address = channel.getRemoteAddress(); + URL url = channel.getUrl(); + return url.getPort() == address.getPort() && + NetUtils.filterLocalHost(channel.getUrl().getIp()) + .equals(NetUtils.filterLocalHost(address.getAddress().getHostAddress())); + } + + Invoker getInvoker(Channel channel, Invocation inv) throws RemotingException{ + boolean isCallBackServiceInvoke = false; + boolean isStubServiceInvoke = false; + int port = channel.getLocalAddress().getPort(); + String path = inv.getAttachments().get(Constants.PATH_KEY); + //如果是客户端的回调服务. + isStubServiceInvoke = Boolean.TRUE.toString().equals(inv.getAttachments().get(Constants.STUB_EVENT_KEY)); + if (isStubServiceInvoke){ + port = channel.getRemoteAddress().getPort(); + } + //callback + isCallBackServiceInvoke = isClientSide(channel) && !isStubServiceInvoke; + if(isCallBackServiceInvoke){ + path = inv.getAttachments().get(Constants.PATH_KEY)+"."+inv.getAttachments().get(Constants.CALLBACK_SERVICE_KEY); + inv.getAttachments().put(IS_CALLBACK_SERVICE_INVOKE, Boolean.TRUE.toString()); + } + String serviceKey = serviceKey(port, path, inv.getAttachments().get(Constants.VERSION_KEY), inv.getAttachments().get(Constants.GROUP_KEY)); + + DubboExporter exporter = (DubboExporter) exporterMap.get(serviceKey); + + if (exporter == null) + throw new RemotingException(channel, "Not found exported service: " + serviceKey + " in " + exporterMap.keySet() + ", may be version or group mismatch " + ", channel: consumer: " + channel.getRemoteAddress() + " --> provider: " + channel.getLocalAddress() + ", message:" + inv); + + return exporter.getInvoker(); + } + public Collection> getInvokers() { return Collections.unmodifiableCollection(invokers); } @@ -242,38 +247,76 @@ public Exporter export(Invoker invoker) throws RpcException { String stubServiceMethods = url.getParameter(Constants.STUB_EVENT_METHODS_KEY); if (stubServiceMethods == null || stubServiceMethods.length() == 0 ){ if (logger.isWarnEnabled()){ - logger.warn( new IllegalStateException("consumer ["+url.getParameter(Constants.INTERFACE_KEY)+"], has set stubproxy support event ,but no stub methods founded.")); + logger.warn(new IllegalStateException("consumer [" +url.getParameter(Constants.INTERFACE_KEY) + + "], has set stubproxy support event ,but no stub methods founded.")); } } else { stubServiceMethodsMap.put(url.getServiceKey(), stubServiceMethods); } - } - - openServer(url); - - return exporter; - } - - private void openServer(URL url) { - // find server. - String key = url.getAddress(); - //client 也可以暴露一个只有server可以调用的服务。 - boolean isServer = url.getParameter(Constants.IS_SERVER_KEY,true); - if (isServer) { - ExchangeServer server = serverMap.get(key); - if (server == null) { - serverMap.put(key, getServer(url)); - } else { - //server支持reset,配合override功能使用 - server.reset(url); - } - } - } + } + + openServer(url); + + // modified by lishen + optimizeSerialization(url); + + return exporter; + } + + private void optimizeSerialization(URL url) throws RpcException { + String className = url.getParameter(Constants.OPTIMIZER_KEY, ""); + if (StringUtils.isEmpty(className) || optimizers.contains(className)) { + return; + } + + logger.info("Optimizing the serialization process for Kryo, FST, etc..."); + + try { + Class clazz = Thread.currentThread().getContextClassLoader().loadClass(className); + if (!SerializationOptimizer.class.isAssignableFrom(clazz)) { + throw new RpcException("The serialization optimizer " + className + " isn't an instance of " + SerializationOptimizer.class.getName()); + } + + SerializationOptimizer optimizer = (SerializationOptimizer) clazz.newInstance(); + + if (optimizer.getSerializableClasses() == null) { + return; + } + + for (Class c : optimizer.getSerializableClasses()) { + SerializableClassRegistry.registerClass(c); + } + + optimizers.add(className); + } catch (ClassNotFoundException e) { + throw new RpcException("Cannot find the serialization optimizer class: " + className, e); + } catch (InstantiationException e) { + throw new RpcException("Cannot instantiate the serialization optimizer class: " + className, e); + } catch (IllegalAccessException e) { + throw new RpcException("Cannot instantiate the serialization optimizer class: " + className, e); + } + } + + private void openServer(URL url) { + // find server. + String key = url.getAddress(); + //client 也可以暴露一个只有server可以调用的服务。 + boolean isServer = url.getParameter(Constants.IS_SERVER_KEY,true); + if (isServer) { + ExchangeServer server = serverMap.get(key); + if (server == null) { + serverMap.put(key, createServer(url)); + } else { + //server支持reset,配合override功能使用 + server.reset(url); + } + } + } - private ExchangeServer getServer(URL url) { - //默认开启server关闭时发送readonly事件 - url = url.addParameterIfAbsent(Constants.CHANNEL_READONLYEVENT_SENT_KEY, Boolean.TRUE.toString()); - //默认开启heartbeat + private ExchangeServer createServer(URL url) { + //默认开启server关闭时发送readonly事件 + url = url.addParameterIfAbsent(Constants.CHANNEL_READONLYEVENT_SENT_KEY, Boolean.TRUE.toString()); + //默认开启heartbeat url = url.addParameterIfAbsent(Constants.HEARTBEAT_KEY, String.valueOf(Constants.DEFAULT_HEARTBEAT)); String str = url.getParameter(Constants.SERVER_KEY, Constants.DEFAULT_REMOTING_SERVER); @@ -295,96 +338,99 @@ private ExchangeServer getServer(URL url) { } } return server; - } + } + + public Invoker refer(Class serviceType, URL url) throws RpcException { + + // modified by lishen + optimizeSerialization(url); - public Invoker refer(Class serviceType, URL url) throws RpcException { // create rpc invoker. DubboInvoker invoker = new DubboInvoker(serviceType, url, getClients(url), invokers); - invokers.add(invoker); + invokers.add(invoker); return invoker; - } - - private ExchangeClient[] getClients(URL url){ - //是否共享连接 - boolean service_share_connect = false; - int connections = url.getParameter(Constants.CONNECTIONS_KEY, 0); - //如果connections不配置,则共享连接,否则每服务每连接 - if (connections == 0){ - service_share_connect = true; - connections = 1; - } - - ExchangeClient[] clients = new ExchangeClient[connections]; - for (int i = 0; i < clients.length; i++) { - if (service_share_connect){ - clients[i] = getSharedClient(url); - } else { - clients[i] = initClient(url); - } - } - return clients; - } - - /** - *获取共享连接 - */ - private ExchangeClient getSharedClient(URL url){ - String key = url.getAddress(); - ReferenceCountExchangeClient client = referenceClientMap.get(key); - if ( client != null ){ - if ( !client.isClosed()){ - client.incrementAndGetCount(); - return client; - } else { -// logger.warn(new IllegalStateException("client is closed,but stay in clientmap .client :"+ client)); - referenceClientMap.remove(key); - } - } - ExchangeClient exchagneclient = initClient(url); - - client = new ReferenceCountExchangeClient(exchagneclient, ghostClientMap); - referenceClientMap.put(key, client); - ghostClientMap.remove(key); - return client; + } + + private ExchangeClient[] getClients(URL url){ + //是否共享连接 + boolean service_share_connect = false; + int connections = url.getParameter(Constants.CONNECTIONS_KEY, 0); + //如果connections不配置,则共享连接,否则每服务每连接 + if (connections == 0){ + service_share_connect = true; + connections = 1; + } + + ExchangeClient[] clients = new ExchangeClient[connections]; + for (int i = 0; i < clients.length; i++) { + if (service_share_connect){ + clients[i] = getSharedClient(url); + } else { + clients[i] = initClient(url); + } + } + return clients; + } + + /** + *获取共享连接 + */ + private ExchangeClient getSharedClient(URL url){ + String key = url.getAddress(); + ReferenceCountExchangeClient client = referenceClientMap.get(key); + if ( client != null ){ + if ( !client.isClosed()){ + client.incrementAndGetCount(); + return client; + } else { +// logger.warn(new IllegalStateException("client is closed,but stay in clientmap .client :"+ client)); + referenceClientMap.remove(key); + } + } + ExchangeClient exchagneclient = initClient(url); + + client = new ReferenceCountExchangeClient(exchagneclient, ghostClientMap); + referenceClientMap.put(key, client); + ghostClientMap.remove(key); + return client; } - /** - * 创建新连接. - */ - private ExchangeClient initClient(URL url) { - + /** + * 创建新连接. + */ + private ExchangeClient initClient(URL url) { + // client type setting. String str = url.getParameter(Constants.CLIENT_KEY, url.getParameter(Constants.SERVER_KEY, Constants.DEFAULT_REMOTING_CLIENT)); String version = url.getParameter(Constants.DUBBO_VERSION_KEY); boolean compatible = (version != null && version.startsWith("1.0.")); url = url.addParameter(Constants.CODEC_KEY, Version.isCompatibleVersion() && compatible ? COMPATIBLE_CODEC_NAME : DubboCodec.NAME); - //默认开启heartbeat - url = url.addParameterIfAbsent(Constants.HEARTBEAT_KEY, String.valueOf(Constants.DEFAULT_HEARTBEAT)); + //默认开启heartbeat + url = url.addParameterIfAbsent(Constants.HEARTBEAT_KEY, String.valueOf(Constants.DEFAULT_HEARTBEAT)); // BIO存在严重性能问题,暂时不允许使用 if (str != null && str.length() > 0 && ! ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(str)) { throw new RpcException("Unsupported client type: " + str + "," + " supported client type is " + StringUtils.join(ExtensionLoader.getExtensionLoader(Transporter.class).getSupportedExtensions(), " ")); } - - ExchangeClient client ; + + ExchangeClient client ; try { //设置连接应该是lazy的 if (url.getParameter(Constants.LAZY_CONNECT_KEY, false)){ client = new LazyConnectExchangeClient(url ,requestHandler); } else { client = Exchangers.connect(url ,requestHandler); - } - } catch (RemotingException e) { - throw new RpcException("Fail to create remoting client for service(" + url - + "): " + e.getMessage(), e); - } - return client; + } + } catch (RemotingException e) { + throw new RpcException("Fail to create remoting client for service(" + url + + "): " + e.getMessage(), e); + } + return client; } public void destroy() { - super.destroy(); for (String key : new ArrayList(serverMap.keySet())) { ExchangeServer server = serverMap.remove(key); if (server != null) { @@ -397,35 +443,36 @@ public void destroy() { logger.warn(t.getMessage(), t); } } - } - - for (String key : new ArrayList(referenceClientMap.keySet())) { - ExchangeClient client = referenceClientMap.remove(key); - if (client != null) { - try { - if (logger.isInfoEnabled()) { - logger.info("Close dubbo connect: " + client.getLocalAddress() + "-->" + client.getRemoteAddress()); - } - client.close(); - } catch (Throwable t) { - logger.warn(t.getMessage(), t); - } - } - } - - for (String key : new ArrayList(ghostClientMap.keySet())) { - ExchangeClient client = ghostClientMap.remove(key); - if (client != null) { - try { - if (logger.isInfoEnabled()) { - logger.info("Close dubbo connect: " + client.getLocalAddress() + "-->" + client.getRemoteAddress()); - } - client.close(); - } catch (Throwable t) { - logger.warn(t.getMessage(), t); - } - } + } + + for (String key : new ArrayList(referenceClientMap.keySet())) { + ExchangeClient client = referenceClientMap.remove(key); + if (client != null) { + try { + if (logger.isInfoEnabled()) { + logger.info("Close dubbo connect: " + client.getLocalAddress() + "-->" + client.getRemoteAddress()); + } + client.close(); + } catch (Throwable t) { + logger.warn(t.getMessage(), t); + } + } + } + + for (String key : new ArrayList(ghostClientMap.keySet())) { + ExchangeClient client = ghostClientMap.remove(key); + if (client != null) { + try { + if (logger.isInfoEnabled()) { + logger.info("Close dubbo connect: " + client.getLocalAddress() + "-->" + client.getRemoteAddress()); + } + client.close(); + } catch (Throwable t) { + logger.warn(t.getMessage(), t); + } + } } stubServiceMethodsMap.clear(); + super.destroy(); } } \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-default/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.remoting.Codec b/dubbo-rpc/dubbo-rpc-default/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.remoting.Codec2 similarity index 100% rename from dubbo-rpc/dubbo-rpc-default/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.remoting.Codec rename to dubbo-rpc/dubbo-rpc-default/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.remoting.Codec2 diff --git a/dubbo-rpc/dubbo-rpc-default/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboProtocolTest.java b/dubbo-rpc/dubbo-rpc-default/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboProtocolTest.java index 118517ad3b22..5183dadb4ade 100644 --- a/dubbo-rpc/dubbo-rpc-default/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboProtocolTest.java +++ b/dubbo-rpc/dubbo-rpc-default/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboProtocolTest.java @@ -1,43 +1,44 @@ -/* - * Copyright 1999-2011 Alibaba Group. - * - * Licensed 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. - */ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.dubbo; -import static junit.framework.Assert.assertEquals; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import junit.framework.Assert; - -import org.junit.Test; - -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.RpcException; -import com.alibaba.dubbo.rpc.protocol.dubbo.support.DemoService; -import com.alibaba.dubbo.rpc.protocol.dubbo.support.DemoServiceImpl; -import com.alibaba.dubbo.rpc.protocol.dubbo.support.NonSerialized; -import com.alibaba.dubbo.rpc.protocol.dubbo.support.RemoteService; -import com.alibaba.dubbo.rpc.protocol.dubbo.support.RemoteServiceImpl; -import com.alibaba.dubbo.rpc.protocol.dubbo.support.Type; -import com.alibaba.dubbo.rpc.service.EchoService; +import static junit.framework.Assert.assertEquals; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import junit.framework.Assert; + +import org.junit.Test; + +import com.alibaba.dubbo.common.Constants; +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.RpcException; +import com.alibaba.dubbo.rpc.protocol.dubbo.support.DemoService; +import com.alibaba.dubbo.rpc.protocol.dubbo.support.DemoServiceImpl; +import com.alibaba.dubbo.rpc.protocol.dubbo.support.NonSerialized; +import com.alibaba.dubbo.rpc.protocol.dubbo.support.RemoteService; +import com.alibaba.dubbo.rpc.protocol.dubbo.support.RemoteServiceImpl; +import com.alibaba.dubbo.rpc.protocol.dubbo.support.Type; +import com.alibaba.dubbo.rpc.service.EchoService; /** * ProxiesTest @@ -65,11 +66,11 @@ public void testDubboProtocol() throws Exception service = proxy.getProxy(protocol.refer(DemoService.class, URL.valueOf("dubbo://127.0.0.1:9010/" + DemoService.class.getName()))); assertEquals(service.enumlength(new Type[]{}), Type.Lower); assertEquals(service.getSize(null), -1); - assertEquals(service.getSize(new String[]{"", "", ""}), 3); - Map map = new HashMap(); - map.put("aa", "bb"); - Set set = service.keys(map); - assertEquals(set.size(), 1); + assertEquals(service.getSize(new String[]{"", "", ""}), 3); + Map map = new HashMap(); + map.put("aa", "bb"); + Set set = service.keys(map); + assertEquals(set.size(), 1); assertEquals(set.iterator().next(), "aa"); service.invoke("dubbo://127.0.0.1:9010/" + DemoService.class.getName() + "", "invoke"); @@ -87,30 +88,66 @@ public void testDubboProtocol() throws Exception assertEquals(echo.$echo("abcdefg"), "abcdefg"); assertEquals(echo.$echo(1234), 1234); } - - @Test - public void testDubboProtocolMultiService() throws Exception - { - DemoService service = new DemoServiceImpl(); - protocol.export(proxy.getInvoker(service, DemoService.class, URL.valueOf("dubbo://127.0.0.1:9010/" + DemoService.class.getName()))); - service = proxy.getProxy(protocol.refer(DemoService.class, URL.valueOf("dubbo://127.0.0.1:9010/" + DemoService.class.getName()))); - - RemoteService remote = new RemoteServiceImpl(); - protocol.export(proxy.getInvoker(remote, RemoteService.class, URL.valueOf("dubbo://127.0.0.1:9010/" + RemoteService.class.getName()))); - remote = proxy.getProxy(protocol.refer(RemoteService.class, URL.valueOf("dubbo://127.0.0.1:9010/" + RemoteService.class.getName()))); - - service.sayHello("world"); - - // test netty client - assertEquals("world", service.echo("world")); - assertEquals("hello world@" + RemoteServiceImpl.class.getName(), remote.sayHello("world")); - - EchoService serviceEcho = (EchoService)service; - assertEquals(serviceEcho.$echo("test"), "test"); - - EchoService remoteEecho = (EchoService)remote; - assertEquals(remoteEecho.$echo("ok"), "ok"); - } + + @Test + public void testDubboProtocolWithMina() throws Exception { + DemoService service = new DemoServiceImpl(); + protocol.export(proxy.getInvoker(service, DemoService.class, URL.valueOf("dubbo://127.0.0.1:9010/" + DemoService.class.getName()).addParameter(Constants.SERVER_KEY, "mina"))); + service = proxy.getProxy(protocol.refer(DemoService.class, URL.valueOf("dubbo://127.0.0.1:9010/" + DemoService.class.getName()).addParameter(Constants.CLIENT_KEY, "mina"))); + for (int i = 0; i < 10; i++) { + assertEquals(service.enumlength(new Type[]{}), Type.Lower); + assertEquals(service.getSize(null), -1); + assertEquals(service.getSize(new String[]{"", "", ""}), 3); + } + Map map = new HashMap(); + map.put("aa", "bb"); + for(int i = 0; i < 10; i++) { + Set set = service.keys(map); + assertEquals(set.size(), 1); + assertEquals(set.iterator().next(), "aa"); + service.invoke("dubbo://127.0.0.1:9010/" + DemoService.class.getName() + "", "invoke"); + } + + service = proxy.getProxy(protocol.refer(DemoService.class, URL.valueOf("dubbo://127.0.0.1:9010/" + DemoService.class.getName() + "?client=mina"))); + // test netty client + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < 1024 * 32 + 32; i++) + buf.append('A'); + System.out.println(service.stringLength(buf.toString())); + + // cast to EchoService + EchoService echo = proxy.getProxy(protocol.refer(EchoService.class, URL.valueOf("dubbo://127.0.0.1:9010/" + DemoService.class.getName() + "?client=mina"))); + for (int i = 0; i < 10; i++) { + assertEquals(echo.$echo(buf.toString()), buf.toString()); + assertEquals(echo.$echo("test"), "test"); + assertEquals(echo.$echo("abcdefg"), "abcdefg"); + assertEquals(echo.$echo(1234), 1234); + } + } + + @Test + public void testDubboProtocolMultiService() throws Exception + { + DemoService service = new DemoServiceImpl(); + protocol.export(proxy.getInvoker(service, DemoService.class, URL.valueOf("dubbo://127.0.0.1:9010/" + DemoService.class.getName()))); + service = proxy.getProxy(protocol.refer(DemoService.class, URL.valueOf("dubbo://127.0.0.1:9010/" + DemoService.class.getName()))); + + RemoteService remote = new RemoteServiceImpl(); + protocol.export(proxy.getInvoker(remote, RemoteService.class, URL.valueOf("dubbo://127.0.0.1:9010/" + RemoteService.class.getName()))); + remote = proxy.getProxy(protocol.refer(RemoteService.class, URL.valueOf("dubbo://127.0.0.1:9010/" + RemoteService.class.getName()))); + + service.sayHello("world"); + + // test netty client + assertEquals("world", service.echo("world")); + assertEquals("hello world@" + RemoteServiceImpl.class.getName(), remote.sayHello("world")); + + EchoService serviceEcho = (EchoService)service; + assertEquals(serviceEcho.$echo("test"), "test"); + + EchoService remoteEecho = (EchoService)remote; + assertEquals(remoteEecho.$echo("ok"), "ok"); + } @Test public void testPerm() throws Exception @@ -122,33 +159,33 @@ public void testPerm() throws Exception for(int i=0;i<1000;i++) service.getSize(new String[]{"", "", ""}); System.out.println("take:"+(System.currentTimeMillis()-start)); - } - - @Test - public void testNonSerializedParameter() throws Exception - { - DemoService service = new DemoServiceImpl(); - protocol.export(proxy.getInvoker(service, DemoService.class, URL.valueOf("dubbo://127.0.0.1:9050/" + DemoService.class.getName() + "?codec=exchange"))); - service = proxy.getProxy(protocol.refer(DemoService.class, URL.valueOf("dubbo://127.0.0.1:9050/" + DemoService.class.getName() + "?codec=exchange"))); - try { - service.nonSerializedParameter(new NonSerialized()); - Assert.fail(); - } catch (RpcException e) { - Assert.assertTrue(e.getMessage().contains("com.alibaba.dubbo.rpc.protocol.dubbo.support.NonSerialized must implement java.io.Serializable")); - } - } - - @Test - public void testReturnNonSerialized() throws Exception - { - DemoService service = new DemoServiceImpl(); - protocol.export(proxy.getInvoker(service, DemoService.class, URL.valueOf("dubbo://127.0.0.1:9050/" + DemoService.class.getName() + "?codec=exchange"))); - service = proxy.getProxy(protocol.refer(DemoService.class, URL.valueOf("dubbo://127.0.0.1:9050/" + DemoService.class.getName() + "?codec=exchange"))); - try { - service.returnNonSerialized(); - Assert.fail(); - } catch (RpcException e) { - Assert.assertTrue(e.getMessage().contains("com.alibaba.dubbo.rpc.protocol.dubbo.support.NonSerialized must implement java.io.Serializable")); - } + } + + @Test + public void testNonSerializedParameter() throws Exception + { + DemoService service = new DemoServiceImpl(); + protocol.export(proxy.getInvoker(service, DemoService.class, URL.valueOf("dubbo://127.0.0.1:9050/" + DemoService.class.getName() + "?codec=exchange"))); + service = proxy.getProxy(protocol.refer(DemoService.class, URL.valueOf("dubbo://127.0.0.1:9050/" + DemoService.class.getName() + "?codec=exchange"))); + try { + service.nonSerializedParameter(new NonSerialized()); + Assert.fail(); + } catch (RpcException e) { + Assert.assertTrue(e.getMessage().contains("com.alibaba.dubbo.rpc.protocol.dubbo.support.NonSerialized must implement java.io.Serializable")); + } + } + + @Test + public void testReturnNonSerialized() throws Exception + { + DemoService service = new DemoServiceImpl(); + protocol.export(proxy.getInvoker(service, DemoService.class, URL.valueOf("dubbo://127.0.0.1:9050/" + DemoService.class.getName() + "?codec=exchange"))); + service = proxy.getProxy(protocol.refer(DemoService.class, URL.valueOf("dubbo://127.0.0.1:9050/" + DemoService.class.getName() + "?codec=exchange"))); + try { + service.returnNonSerialized(); + Assert.fail(); + } catch (RpcException e) { + Assert.assertTrue(e.getMessage().contains("com.alibaba.dubbo.rpc.protocol.dubbo.support.NonSerialized must implement java.io.Serializable")); + } } } \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-hessian/pom.xml b/dubbo-rpc/dubbo-rpc-hessian/pom.xml index e58f0ca4ebba..bf5e50cb4c61 100644 --- a/dubbo-rpc/dubbo-rpc-hessian/pom.xml +++ b/dubbo-rpc/dubbo-rpc-hessian/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-rpc - 2.4.3 + 2.8.4 dubbo-rpc-hessian jar diff --git a/dubbo-rpc/dubbo-rpc-http/pom.xml b/dubbo-rpc/dubbo-rpc-http/pom.xml index d142796fa0ea..a2ad7c134f39 100644 --- a/dubbo-rpc/dubbo-rpc-http/pom.xml +++ b/dubbo-rpc/dubbo-rpc-http/pom.xml @@ -1,12 +1,12 @@ + + 4.0.0 + + com.alibaba + dubbo-rpc + 2.8.4 + + dubbo-rpc-rest + jar + ${project.artifactId} + The JAX-RS rpc module of dubbo project + + true + + + + com.alibaba + dubbo-rpc-api + ${project.parent.version} + + + + com.alibaba + dubbo-remoting-http + ${project.parent.version} + + + + org.jboss.resteasy + resteasy-jaxrs + + + + org.jboss.resteasy + resteasy-client + + + + javax.validation + validation-api + + + + + + org.jboss.resteasy + resteasy-netty + + + + org.jboss.resteasy + resteasy-jdk-http + + + + + + + + + + + + + + + + + + + + + + + + + + org.jboss.resteasy + resteasy-jackson-provider + + + + org.jboss.resteasy + resteasy-jaxb-provider + + + \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/BaseRestServer.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/BaseRestServer.java new file mode 100644 index 000000000000..a788043e669d --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/BaseRestServer.java @@ -0,0 +1,64 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.rest; + +import com.alibaba.dubbo.common.Constants; +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.utils.StringUtils; +import org.jboss.resteasy.spi.ResteasyDeployment; + +/** + * @author lishen + */ +public abstract class BaseRestServer implements RestServer { + + public void start(URL url) { + getDeployment().getMediaTypeMappings().put("json", "application/json"); + getDeployment().getMediaTypeMappings().put("xml", "text/xml"); +// server.getDeployment().getMediaTypeMappings().put("xml", "application/xml"); + getDeployment().getProviderClasses().add(RpcContextFilter.class.getName()); + // TODO users can override this mapper, but we just rely on the current priority strategy of resteasy + getDeployment().getProviderClasses().add(RpcExceptionMapper.class.getName()); + + loadProviders(url.getParameter(Constants.EXTENSION_KEY, "")); + + doStart(url); + } + + public void deploy(Class resourceDef, Object resourceInstance, String contextPath) { + if (StringUtils.isEmpty(contextPath)) { + getDeployment().getRegistry().addResourceFactory(new DubboResourceFactory(resourceInstance, resourceDef)); + } else { + getDeployment().getRegistry().addResourceFactory(new DubboResourceFactory(resourceInstance, resourceDef), contextPath); + } + } + + public void undeploy(Class resourceDef) { + getDeployment().getRegistry().removeRegistrations(resourceDef); + } + + protected void loadProviders(String value) { + for (String clazz : Constants.COMMA_SPLIT_PATTERN.split(value)) { + if (!StringUtils.isEmpty(clazz)) { + getDeployment().getProviderClasses().add(clazz.trim()); + } + } + } + + protected abstract ResteasyDeployment getDeployment(); + + protected abstract void doStart(URL url); +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/DubboHttpServer.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/DubboHttpServer.java new file mode 100644 index 000000000000..92d259907db4 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/DubboHttpServer.java @@ -0,0 +1,122 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.rest; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.remoting.http.HttpBinder; +import com.alibaba.dubbo.remoting.http.HttpHandler; +import com.alibaba.dubbo.remoting.http.HttpServer; +import com.alibaba.dubbo.remoting.http.servlet.BootstrapListener; +import com.alibaba.dubbo.remoting.http.servlet.ServletManager; +import com.alibaba.dubbo.rpc.RpcContext; +import com.alibaba.dubbo.rpc.RpcException; +import org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher; +import org.jboss.resteasy.spi.ResteasyDeployment; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Enumeration; + +/** + * @author lishen + */ +public class DubboHttpServer extends BaseRestServer { + + private final HttpServletDispatcher dispatcher = new HttpServletDispatcher(); + private final ResteasyDeployment deployment = new ResteasyDeployment(); + private HttpBinder httpBinder; + private HttpServer httpServer; +// private boolean isExternalServer; + + public DubboHttpServer(HttpBinder httpBinder) { + this.httpBinder = httpBinder; + } + + protected void doStart(URL url) { + // TODO jetty will by default enable keepAlive so the xml config has no effect now + httpServer = httpBinder.bind(url, new RestHandler()); + + ServletContext servletContext = ServletManager.getInstance().getServletContext(url.getPort()); + if (servletContext == null) { + servletContext = ServletManager.getInstance().getServletContext(ServletManager.EXTERNAL_SERVER_PORT); + } + if (servletContext == null) { + throw new RpcException("No servlet context found. If you are using server='servlet', " + + "make sure that you've configured " + BootstrapListener.class.getName() + " in web.xml"); + } + + servletContext.setAttribute(ResteasyDeployment.class.getName(), deployment); + + try { + dispatcher.init(new SimpleServletConfig(servletContext)); + } catch (ServletException e) { + throw new RpcException(e); + } + } + + public void stop() { + httpServer.close(); + } + + protected ResteasyDeployment getDeployment() { + return deployment; + } + + private class RestHandler implements HttpHandler { + + public void handle(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + RpcContext.getContext().setRemoteAddress(request.getRemoteAddr(), request.getRemotePort()); + dispatcher.service(request, response); + } + } + + private static class SimpleServletConfig implements ServletConfig { + + private final ServletContext servletContext; + + public SimpleServletConfig(ServletContext servletContext) { + this.servletContext = servletContext; + } + + public String getServletName() { + return "DispatcherServlet"; + } + + public ServletContext getServletContext() { + return servletContext; + } + + public String getInitParameter(String s) { + return null; + } + + public Enumeration getInitParameterNames() { + return new Enumeration() { + public boolean hasMoreElements() { + return false; + } + + public Object nextElement() { + return null; + } + }; + } + } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/DubboResourceFactory.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/DubboResourceFactory.java new file mode 100644 index 000000000000..c28cc22518de --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/DubboResourceFactory.java @@ -0,0 +1,71 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.rest; + +import org.jboss.resteasy.spi.HttpRequest; +import org.jboss.resteasy.spi.HttpResponse; +import org.jboss.resteasy.spi.ResourceFactory; +import org.jboss.resteasy.spi.ResteasyProviderFactory; + +/** + * We don't support propertyInjector here since the resource impl should be singleton in dubbo + * + * @author lishen + */ +public class DubboResourceFactory implements ResourceFactory { + + private Object resourceInstance; + private Class scannableClass; +// private PropertyInjector propertyInjector; +// private String context = null; + + public DubboResourceFactory(Object resourceInstance, Class scannableClass) { + this.resourceInstance = resourceInstance; + this.scannableClass = scannableClass; + } + +// public PropertyInjector getPropertyInjector() { +// return propertyInjector; +// } + + public Object createResource(HttpRequest request, HttpResponse response, + ResteasyProviderFactory factory) { + return resourceInstance; + } + + public Class getScannableClass() { + return scannableClass; + } + + public void registered(ResteasyProviderFactory factory) { +// this.propertyInjector = factory.getInjectorFactory().createPropertyInjector(getScannableClass(), factory); + } + + public void requestFinished(HttpRequest request, HttpResponse response, + Object resource) { + } + + public void unregistered() { + } + +// public void setContext(String context) { +// this.context = context; +// } +// +// public String getContext() { +// return context; +// } +} \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/NettyServer.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/NettyServer.java new file mode 100644 index 000000000000..2bfdd65ebc5f --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/NettyServer.java @@ -0,0 +1,47 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.rest; + +import com.alibaba.dubbo.common.Constants; +import com.alibaba.dubbo.common.URL; +import org.jboss.resteasy.plugins.server.netty.NettyJaxrsServer; +import org.jboss.resteasy.spi.ResteasyDeployment; + +/** + * Netty server can't support @Context injection of servlet objects since it's not a servlet container + * + * @author lishen + */ +public class NettyServer extends BaseRestServer { + + private final NettyJaxrsServer server = new NettyJaxrsServer(); + + protected void doStart(URL url) { + server.setPort(url.getPort()); + server.setKeepAlive(url.getParameter(Constants.KEEP_ALIVE_KEY, Constants.DEFAULT_KEEP_ALIVE)); + server.setExecutorThreadCount(url.getParameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS)); + server.setIoWorkerCount(url.getParameter(Constants.IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS)); + server.start(); + } + + public void stop() { + server.stop(); + } + + protected ResteasyDeployment getDeployment() { + return server.getDeployment(); + } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/RestConstraintViolation.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/RestConstraintViolation.java new file mode 100644 index 000000000000..8c73243efce3 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/RestConstraintViolation.java @@ -0,0 +1,68 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.rest; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; + +/** + * @author lishen + */ +@XmlRootElement(name = "constraintViolation") +@XmlAccessorType(XmlAccessType.FIELD) +public class RestConstraintViolation implements Serializable { + + private static final long serialVersionUID = -23497234978L; + + private String path; + private String message; + private String value; + + public RestConstraintViolation(String path, String message, String value) { + this.path = path; + this.message = message; + this.value = value; + } + + public RestConstraintViolation() { + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/RestProtocol.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/RestProtocol.java new file mode 100644 index 000000000000..918f28f91a15 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/RestProtocol.java @@ -0,0 +1,265 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.rest; + +import com.alibaba.dubbo.common.Constants; +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.utils.StringUtils; +import com.alibaba.dubbo.remoting.http.HttpBinder; +import com.alibaba.dubbo.remoting.http.servlet.BootstrapListener; +import com.alibaba.dubbo.remoting.http.servlet.ServletManager; +import com.alibaba.dubbo.rpc.RpcException; +import com.alibaba.dubbo.rpc.protocol.AbstractProxyProtocol; +import com.alibaba.dubbo.rpc.ServiceClassHolder; +import org.apache.http.HeaderElement; +import org.apache.http.HeaderElementIterator; +import org.apache.http.HttpResponse; +import org.apache.http.conn.ClientConnectionManager; +import org.apache.http.conn.ConnectionKeepAliveStrategy; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.impl.conn.PoolingClientConnectionManager; +import org.apache.http.message.BasicHeaderElementIterator; +import org.apache.http.params.HttpConnectionParams; +import org.apache.http.params.HttpParams; +import org.apache.http.protocol.HTTP; +import org.apache.http.protocol.HttpContext; +import org.jboss.resteasy.client.jaxrs.ResteasyClient; +import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; +import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget; +import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine; +import org.jboss.resteasy.util.GetRestful; + +import javax.servlet.ServletContext; +import javax.ws.rs.ProcessingException; +import javax.ws.rs.WebApplicationException; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +/** + * @author lishen + */ +public class RestProtocol extends AbstractProxyProtocol { + + private static final int DEFAULT_PORT = 80; + + private final Map servers = new ConcurrentHashMap(); + + private final RestServerFactory serverFactory = new RestServerFactory(); + + // TODO in the future maybe we can just use a single rest client and connection manager + private final List clients = Collections.synchronizedList(new LinkedList()); + + private volatile ConnectionMonitor connectionMonitor; + + public RestProtocol() { + super(WebApplicationException.class, ProcessingException.class); + } + + public void setHttpBinder(HttpBinder httpBinder) { + serverFactory.setHttpBinder(httpBinder); + } + + public int getDefaultPort() { + return DEFAULT_PORT; + } + + protected Runnable doExport(T impl, Class type, URL url) throws RpcException { + String addr = url.getIp() + ":" + url.getPort(); + Class implClass = ServiceClassHolder.getInstance().popServiceClass(); + RestServer server = servers.get(addr); + if (server == null) { + server = serverFactory.createServer(url.getParameter(Constants.SERVER_KEY, "jetty")); + server.start(url); + servers.put(addr, server); + } + + String contextPath = getContextPath(url); + if ("servlet".equalsIgnoreCase(url.getParameter(Constants.SERVER_KEY, "jetty"))) { + ServletContext servletContext = ServletManager.getInstance().getServletContext(ServletManager.EXTERNAL_SERVER_PORT); + if (servletContext == null) { + throw new RpcException("No servlet context found. Since you are using server='servlet', " + + "make sure that you've configured " + BootstrapListener.class.getName() + " in web.xml"); + } + String webappPath = servletContext.getContextPath(); + if (StringUtils.isNotEmpty(webappPath)) { + webappPath = webappPath.substring(1); + if (!contextPath.startsWith(webappPath)) { + throw new RpcException("Since you are using server='servlet', " + + "make sure that the 'contextpath' property starts with the path of external webapp"); + } + contextPath = contextPath.substring(webappPath.length()); + if (contextPath.startsWith("/")) { + contextPath = contextPath.substring(1); + } + } + } + + final Class resourceDef = GetRestful.getRootResourceClass(implClass) != null ? implClass : type; + + server.deploy(resourceDef, impl, contextPath); + + final RestServer s = server; + return new Runnable() { + public void run() { + // TODO due to dubbo's current architecture, + // it will be called from registry protocol in the shutdown process and won't appear in logs + s.undeploy(resourceDef); + } + }; + } + + protected T doRefer(Class serviceType, URL url) throws RpcException { + if (connectionMonitor == null) { + connectionMonitor = new ConnectionMonitor(); + } + + // TODO more configs to add + + PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager(); + // 20 is the default maxTotal of current PoolingClientConnectionManager + connectionManager.setMaxTotal(url.getParameter(Constants.CONNECTIONS_KEY, 20)); + connectionManager.setDefaultMaxPerRoute(url.getParameter(Constants.CONNECTIONS_KEY, 20)); + + connectionMonitor.addConnectionManager(connectionManager); + +// BasicHttpContext localContext = new BasicHttpContext(); + + DefaultHttpClient httpClient = new DefaultHttpClient(connectionManager); + + httpClient.setKeepAliveStrategy(new ConnectionKeepAliveStrategy() { + public long getKeepAliveDuration(HttpResponse response, HttpContext context) { + HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE)); + while (it.hasNext()) { + HeaderElement he = it.nextElement(); + String param = he.getName(); + String value = he.getValue(); + if (value != null && param.equalsIgnoreCase("timeout")) { + return Long.parseLong(value) * 1000; + } + } + // TODO constant + return 30 * 1000; + } + }); + + HttpParams params = httpClient.getParams(); + // TODO currently no xml config for Constants.CONNECT_TIMEOUT_KEY so we directly reuse Constants.TIMEOUT_KEY for now + HttpConnectionParams.setConnectionTimeout(params, url.getParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT)); + HttpConnectionParams.setSoTimeout(params, url.getParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT)); + HttpConnectionParams.setTcpNoDelay(params, true); + HttpConnectionParams.setSoKeepalive(params, true); + + ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient/*, localContext*/); + + ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build(); + clients.add(client); + + client.register(RpcContextFilter.class); + for (String clazz : Constants.COMMA_SPLIT_PATTERN.split(url.getParameter(Constants.EXTENSION_KEY, ""))) { + if (!StringUtils.isEmpty(clazz)) { + try { + client.register(Thread.currentThread().getContextClassLoader().loadClass(clazz.trim())); + } catch (ClassNotFoundException e) { + throw new RpcException("Error loading JAX-RS extension class: " + clazz.trim(), e); + } + } + } + + // TODO protocol + ResteasyWebTarget target = client.target("http://" + url.getHost() + ":" + url.getPort() + "/" + getContextPath(url)); + return target.proxy(serviceType); + } + + protected int getErrorCode(Throwable e) { + // TODO + return super.getErrorCode(e); + } + + public void destroy() { + super.destroy(); + + if (connectionMonitor != null) { + connectionMonitor.shutdown(); + } + + for (Map.Entry entry : servers.entrySet()) { + try { + if (logger.isInfoEnabled()) { + logger.info("Closing the rest server at " + entry.getKey()); + } + entry.getValue().stop(); + } catch (Throwable t) { + logger.warn("Error closing rest server", t); + } + } + servers.clear(); + + if (logger.isInfoEnabled()) { + logger.info("Closing rest clients"); + } + for (ResteasyClient client : clients) { + try { + client.close(); + } catch (Throwable t) { + logger.warn("Error closing rest client", t); + } + } + clients.clear(); + } + + protected String getContextPath(URL url) { + int pos = url.getPath().lastIndexOf("/"); + return pos > 0 ? url.getPath().substring(0, pos) : ""; + } + + protected class ConnectionMonitor extends Thread { + private volatile boolean shutdown; + private final List connectionManagers = Collections.synchronizedList(new LinkedList()); + + public void addConnectionManager(ClientConnectionManager connectionManager) { + connectionManagers.add(connectionManager); + } + + public void run() { + try { + while (!shutdown) { + synchronized (this) { + wait(1000); + for (ClientConnectionManager connectionManager : connectionManagers) { + connectionManager.closeExpiredConnections(); + // TODO constant + connectionManager.closeIdleConnections(30, TimeUnit.SECONDS); + } + } + } + } catch (InterruptedException ex) { + shutdown(); + } + } + + public void shutdown() { + shutdown = true; + connectionManagers.clear(); + synchronized (this) { + notifyAll(); + } + } + } +} \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/RestServer.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/RestServer.java new file mode 100644 index 000000000000..cc989550a06b --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/RestServer.java @@ -0,0 +1,35 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.rest; + +import com.alibaba.dubbo.common.URL; + +/** + * @author lishen + */ +public interface RestServer { + + void start(URL url); + + /** + * @param resourceDef it could be either resource interface or resource impl + */ + void deploy(Class resourceDef, Object resourceInstance, String contextPath); + + void undeploy(Class resourceDef); + + void stop(); +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/RestServerFactory.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/RestServerFactory.java new file mode 100644 index 000000000000..0b7c9b38732c --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/RestServerFactory.java @@ -0,0 +1,48 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.rest; + +import com.alibaba.dubbo.remoting.http.HttpBinder; + +/** + * Only the server that implements servlet container + * could support something like @Context injection of servlet objects. + * + * @author lishen + */ +public class RestServerFactory { + + private HttpBinder httpBinder; + + public void setHttpBinder(HttpBinder httpBinder) { + this.httpBinder = httpBinder; + } + + public RestServer createServer(String name) { + // TODO move names to Constants + if ("servlet".equalsIgnoreCase(name) || "jetty".equalsIgnoreCase(name) || "tomcat".equalsIgnoreCase(name)) { + return new DubboHttpServer(httpBinder); +// } else if ("tjws".equalsIgnoreCase(name)) { +// return new TjwsServer(); + } else if ("netty".equalsIgnoreCase(name)) { + return new NettyServer(); + } else if ("sunhttp".equalsIgnoreCase(name)) { + return new SunHttpServer(); + } else { + throw new IllegalArgumentException("Unrecognized server name: " + name); + } + } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/RpcContextFilter.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/RpcContextFilter.java new file mode 100644 index 000000000000..5c678d964b99 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/RpcContextFilter.java @@ -0,0 +1,90 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.rest; + +import com.alibaba.dubbo.common.utils.StringUtils; +import com.alibaba.dubbo.rpc.RpcContext; +import org.jboss.resteasy.spi.ResteasyProviderFactory; + +import javax.annotation.Priority; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientRequestFilter; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import java.io.IOException; +import java.util.Map; + +/** + * @author lishen + */ +@Priority(Integer.MIN_VALUE + 1) +public class RpcContextFilter implements ContainerRequestFilter, ClientRequestFilter { + + private static final String DUBBO_ATTACHMENT_HEADER = "Dubbo-Attachments"; + + // currently we use a single header to hold the attachments so that the total attachment size limit is about 8k + private static final int MAX_HEADER_SIZE = 8 * 1024; + + public void filter(ContainerRequestContext requestContext) throws IOException { + HttpServletRequest request = ResteasyProviderFactory.getContextData(HttpServletRequest.class); + RpcContext.getContext().setRequest(request); + + // this only works for servlet containers + if (request != null && RpcContext.getContext().getRemoteAddress() == null) { + RpcContext.getContext().setRemoteAddress(request.getRemoteAddr(), request.getRemotePort()); + } + + RpcContext.getContext().setResponse(ResteasyProviderFactory.getContextData(HttpServletResponse.class)); + + String headers = requestContext.getHeaderString(DUBBO_ATTACHMENT_HEADER); + if (headers != null) { + for (String header : headers.split(",")) { + int index = header.indexOf("="); + if (index > 0) { + String key = header.substring(0, index); + String value = header.substring(index + 1); + if (!StringUtils.isEmpty(key)) { + RpcContext.getContext().setAttachment(key.trim(), value.trim()); + } + } + } + } + } + + public void filter(ClientRequestContext requestContext) throws IOException { + int size = 0; + for (Map.Entry entry : RpcContext.getContext().getAttachments().entrySet()) { + if (entry.getValue().contains(",") || entry.getValue().contains("=") + || entry.getKey().contains(",") || entry.getKey().contains("=")) { + throw new IllegalArgumentException("The attachments of " + RpcContext.class.getSimpleName() + " must not contain ',' or '=' when using rest protocol"); + } + + // TODO for now we don't consider the differences of encoding and server limit + size += entry.getValue().getBytes("UTF-8").length; + if (size > MAX_HEADER_SIZE) { + throw new IllegalArgumentException("The attachments of " + RpcContext.class.getSimpleName() + " is too big"); + } + + StringBuilder attachments = new StringBuilder(); + attachments.append(entry.getKey()); + attachments.append("="); + attachments.append(entry.getValue()); + requestContext.getHeaders().add(DUBBO_ATTACHMENT_HEADER, attachments.toString()); + } + } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/RpcExceptionMapper.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/RpcExceptionMapper.java new file mode 100644 index 000000000000..3b0cc31dcae6 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/RpcExceptionMapper.java @@ -0,0 +1,52 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.rest; + +import com.alibaba.dubbo.rpc.RpcException; +import com.alibaba.dubbo.rpc.protocol.rest.support.ContentType; + +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; + +/** + * @author lishen + */ +public class RpcExceptionMapper implements ExceptionMapper { + + public Response toResponse(RpcException e) { + // TODO do more sophisticated exception handling and output + if (e.getCause() instanceof ConstraintViolationException) { + return handleConstraintViolationException((ConstraintViolationException) e.getCause()); + } + // we may want to avoid exposing the dubbo exception details to certain clients + // TODO for now just do plain text output + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("Internal server error: " + e.getMessage()).type(ContentType.TEXT_PLAIN_UTF_8).build(); + } + + protected Response handleConstraintViolationException(ConstraintViolationException cve) { + ViolationReport report = new ViolationReport(); + for (ConstraintViolation cv : cve.getConstraintViolations()) { + report.addConstraintViolation(new RestConstraintViolation( + cv.getPropertyPath().toString(), + cv.getMessage(), + cv.getInvalidValue() == null ? "null" : cv.getInvalidValue().toString())); + } + // TODO for now just do xml output + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(report).type(ContentType.TEXT_XML_UTF_8).build(); + } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/SunHttpServer.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/SunHttpServer.java new file mode 100644 index 000000000000..7e4e51a1e17d --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/SunHttpServer.java @@ -0,0 +1,41 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.rest; + +import com.alibaba.dubbo.common.URL; +import org.jboss.resteasy.plugins.server.sun.http.SunHttpJaxrsServer; +import org.jboss.resteasy.spi.ResteasyDeployment; + +/** + * @author lishen + */ +public class SunHttpServer extends BaseRestServer { + + private final SunHttpJaxrsServer server = new SunHttpJaxrsServer(); + + protected void doStart(URL url) { + server.setPort(url.getPort()); + server.start(); + } + + public void stop() { + server.stop(); + } + + protected ResteasyDeployment getDeployment() { + return server.getDeployment(); + } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/TjwsServer.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/TjwsServer.java new file mode 100644 index 000000000000..3a5e7c5a8a41 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/TjwsServer.java @@ -0,0 +1,45 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.rest; + +import com.alibaba.dubbo.common.URL; +import org.jboss.resteasy.spi.ResteasyDeployment; + +/** + * @author lishen + */ +public class TjwsServer extends BaseRestServer { + +// private final TJWSEmbeddedJaxrsServer server = new TJWSEmbeddedJaxrsServer(); + + protected void doStart(URL url) { + throw new UnsupportedOperationException("TJWS server is now unsupported"); +// server.setPort(url.getPort()); +// // below config is useless due to a resteasy bug +//// server.setKeepAlive(false); +// server.start(); + } + + protected ResteasyDeployment getDeployment() { + throw new UnsupportedOperationException("TJWS server is now unsupported"); +// return server.getDeployment(); + } + + public void stop() { + throw new UnsupportedOperationException("TJWS server is now unsupported"); +// server.stop(); + } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/UndertowServer.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/UndertowServer.java new file mode 100644 index 000000000000..d8d7ff060283 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/UndertowServer.java @@ -0,0 +1,68 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.rest; + +//import com.alibaba.dubbo.common.URL; +//import com.alibaba.dubbo.common.utils.StringUtils; +//import io.undertow.Undertow; +//import io.undertow.servlet.api.DeploymentInfo; +//import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer; +//import org.jboss.resteasy.spi.ResteasyDeployment; + +/** + * TODO this impl hasn't been well tested, and we can consider move undertow to a general remoting-http impl in the future + * + * @author lishen + */ +public class UndertowServer /*implements RestServer*/ { + +// // Note that UndertowJaxrsServer doesn't implement EmbeddedJaxrsServer +// +// private final ResteasyDeployment deployment = new ResteasyDeployment(); +// +// private final UndertowJaxrsServer server = new UndertowJaxrsServer(); +// +// public void start(URL url) { +// deployment.start(); +// DeploymentInfo deploymentInfo = server.undertowDeployment(deployment); +// deploymentInfo.setContextPath("/"); +// deploymentInfo.setDeploymentName("dubbo-rest"); +// deploymentInfo.setClassLoader(Thread.currentThread().getContextClassLoader()); +// server.deploy(deploymentInfo); +// server.start(Undertow.builder().addHttpListener(url.getPort(), url.getHost())); +// } +// +// public void deploy(Class resourceDef, Object resourceInstance, String contextPath) { +// if (StringUtils.isEmpty(contextPath)) { +// deployment.getRegistry().addResourceFactory(new DubboResourceFactory(resourceInstance, resourceDef)); +// } else { +// deployment.getRegistry().addResourceFactory(new DubboResourceFactory(resourceInstance, resourceDef), contextPath); +// } +// } +// +// public void undeploy(Class resourceDef) { +// deployment.getRegistry().removeRegistrations(resourceDef); +// } +// +// public void deploy(Class resourceDef, Object resourceInstance) { +// deploy(resourceDef, resourceInstance, "/"); +// } +// +// public void stop() { +// deployment.stop(); +// server.stop(); +// } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/ViolationReport.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/ViolationReport.java new file mode 100644 index 000000000000..4fa6e5dd086b --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/ViolationReport.java @@ -0,0 +1,50 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.rest; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.LinkedList; +import java.util.List; + +/** + * @author lishen + */ +@XmlRootElement(name="violationReport") +@XmlAccessorType(XmlAccessType.FIELD) +public class ViolationReport implements Serializable { + + private static final long serialVersionUID = -130498234L; + + private List constraintViolations; + + public List getConstraintViolations() { + return constraintViolations; + } + + public void setConstraintViolations(List constraintViolations) { + this.constraintViolations = constraintViolations; + } + + public void addConstraintViolation(RestConstraintViolation constraintViolation) { + if (constraintViolations == null) { + constraintViolations = new LinkedList(); + } + constraintViolations.add(constraintViolation); + } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/support/ContentType.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/support/ContentType.java new file mode 100644 index 000000000000..d3887481347b --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/support/ContentType.java @@ -0,0 +1,28 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.rest.support; + +import javax.ws.rs.core.MediaType; + +/** + * @author lishen + */ +public class ContentType { + + public static final String APPLICATION_JSON_UTF_8 = MediaType.APPLICATION_JSON + "; " + MediaType.CHARSET_PARAMETER + "=UTF-8"; + public static final String TEXT_XML_UTF_8 = MediaType.TEXT_XML + "; " + MediaType.CHARSET_PARAMETER + "=UTF-8"; + public static final String TEXT_PLAIN_UTF_8 = MediaType.TEXT_PLAIN + "; " + MediaType.CHARSET_PARAMETER + "=UTF-8"; +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/support/LoggingFilter.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/support/LoggingFilter.java new file mode 100644 index 000000000000..92b1b4405313 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/com/alibaba/dubbo/rpc/protocol/rest/support/LoggingFilter.java @@ -0,0 +1,141 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.rest.support; + +import com.alibaba.dubbo.common.logger.Logger; +import com.alibaba.dubbo.common.logger.LoggerFactory; +import org.apache.commons.io.IOUtils; + +import javax.annotation.Priority; +import javax.ws.rs.Priorities; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientRequestFilter; +import javax.ws.rs.client.ClientResponseContext; +import javax.ws.rs.client.ClientResponseFilter; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.ReaderInterceptor; +import javax.ws.rs.ext.ReaderInterceptorContext; +import javax.ws.rs.ext.WriterInterceptor; +import javax.ws.rs.ext.WriterInterceptorContext; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; +import java.util.Map; + +/** + * This logging filter is not highly optimized for now + * + * @author lishen + */ +@Priority(Integer.MIN_VALUE) +public class LoggingFilter implements ContainerRequestFilter, ClientRequestFilter, ContainerResponseFilter, ClientResponseFilter, WriterInterceptor, ReaderInterceptor { + + private static final Logger logger = LoggerFactory.getLogger(LoggingFilter.class); + + public void filter(ClientRequestContext context) throws IOException { + logHttpHeaders(context.getStringHeaders()); + } + + public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException { + logHttpHeaders(responseContext.getHeaders()); + } + + public void filter(ContainerRequestContext context) throws IOException { + logHttpHeaders(context.getHeaders()); + } + + public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException { + logHttpHeaders(responseContext.getStringHeaders()); + } + + public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException { + byte[] buffer = IOUtils.toByteArray(context.getInputStream()); + logger.info("The contents of request body is: \n" + new String(buffer, "UTF-8") + "\n"); + context.setInputStream(new ByteArrayInputStream(buffer)); + return context.proceed(); + } + + public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException { + OutputStreamWrapper wrapper = new OutputStreamWrapper(context.getOutputStream()); + context.setOutputStream(wrapper); + context.proceed(); + logger.info("The contents of response body is: \n" + new String(wrapper.getBytes(), "UTF-8") + "\n"); + } + + protected void logHttpHeaders(MultivaluedMap headers) { + StringBuilder msg = new StringBuilder("The HTTP headers are: \n"); + for (Map.Entry> entry : headers.entrySet()) { + msg.append(entry.getKey()).append(": "); + for (int i = 0; i < entry.getValue().size(); i++) { + msg.append(entry.getValue().get(i)); + if (i < entry.getValue().size() - 1) { + msg.append(", "); + } + } + msg.append("\n"); + } + logger.info(msg.toString()); + } + + protected static class OutputStreamWrapper extends OutputStream { + + private final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + private final OutputStream output; + + private OutputStreamWrapper(OutputStream output) { + this.output = output; + } + + @Override + public void write(int i) throws IOException { + buffer.write(i); + output.write(i); + } + + @Override + public void write(byte[] b) throws IOException { + buffer.write(b); + output.write(b); + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + buffer.write(b, off, len); + output.write(b, off, len); + } + + @Override + public void flush() throws IOException { + output.flush(); + } + + @Override + public void close() throws IOException { + output.close(); + } + + public byte[] getBytes() { + return buffer.toByteArray(); + } + } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol b/dubbo-rpc/dubbo-rpc-rest/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol new file mode 100644 index 000000000000..a0f05272d08b --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol @@ -0,0 +1 @@ +rest=com.alibaba.dubbo.rpc.protocol.rest.RestProtocol \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-rmi/pom.xml b/dubbo-rpc/dubbo-rpc-rmi/pom.xml index e25b3e4b9d1f..84b76b9a0593 100644 --- a/dubbo-rpc/dubbo-rpc-rmi/pom.xml +++ b/dubbo-rpc/dubbo-rpc-rmi/pom.xml @@ -1,12 +1,12 @@ + + 4.0.0 + + com.alibaba + dubbo-test + 2.8.4 + + dubbo-test-benchmark-client + jar + ${project.artifactId} + The benchmark test module of dubbo project + + true + + + + com.alibaba + dubbo + ${project.parent.version} + + + com.alibaba + dubbo-test-benchmark-api + ${project.parent.version} + + + commons-lang + commons-lang + 2.6 + + + org.javassist + javassist + + + io.netty + netty + + + org.apache.mina + mina-core + + + org.glassfish.grizzly + grizzly-core + + + org.apache.httpcomponents + httpclient + + + com.alibaba + fastjson + + + com.thoughtworks.xstream + xstream + + + org.apache.bsf + bsf-api + + + org.apache.zookeeper + zookeeper + + + com.github.sgroschupf + zkclient + + + org.apache.curator + curator-framework + + + com.googlecode.xmemcached + xmemcached + + + org.apache.cxf + cxf-rt-frontend-simple + + + org.apache.cxf + cxf-rt-transports-http + + + org.apache.thrift + libthrift + + + com.caucho + hessian + + + javax.servlet + javax.servlet-api + + + org.mortbay.jetty + jetty + + + log4j + log4j + + + org.slf4j + slf4j-api + + + redis.clients + jedis + + + javax.validation + validation-api + + + org.hibernate + hibernate-validator + + + javax.cache + cache-api + + + javax.ws.rs + javax.ws.rs-api + 2.0 + + + + + + + src/main/resources + + **/*.* + + + + + + maven-dependency-plugin + + + unpack + package + + unpack + + + + + com.alibaba + dubbo + ${project.parent.version} + ${project.build.directory}/dubbo + META-INF/assembly/** + + + + + + + + maven-assembly-plugin + + src/assembly/assembly.xml + + + + make-assembly + package + + single + + + + + + + \ No newline at end of file diff --git a/dubbo-test/dubbo-test-benchmark-client/src/assembly/assembly.xml b/dubbo-test/dubbo-test-benchmark-client/src/assembly/assembly.xml new file mode 100644 index 000000000000..0617798a708f --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-client/src/assembly/assembly.xml @@ -0,0 +1,23 @@ + + assembly + + tar.gz + + true + + + src/cli + / + 0755 + + + src/main/resources + conf + + + + + lib + + + \ No newline at end of file diff --git a/dubbo-test/dubbo-test-benchmark-client/src/cli/run.bat b/dubbo-test/dubbo-test-benchmark-client/src/cli/run.bat new file mode 100644 index 000000000000..54b4406fa89b --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-client/src/cli/run.bat @@ -0,0 +1 @@ +java -Xms1g -Xmx1g -XX:PermSize=64M -XX:+UseConcMarkSweepGC -Djava.ext.dirs=lib -classpath conf com.alibaba.dubbo.rpc.benchmark.RpcBenchmarkClient > benchmark.log \ No newline at end of file diff --git a/dubbo-test/dubbo-test-benchmark-client/src/cli/run.sh b/dubbo-test/dubbo-test-benchmark-client/src/cli/run.sh new file mode 100644 index 000000000000..7389f902f9c4 --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-client/src/cli/run.sh @@ -0,0 +1 @@ +java -Xms1g -Xmx1g -XX:PermSize=64M -XX:+UseConcMarkSweepGC -Djava.ext.dirs=./lib -classpath conf com.alibaba.dubbo.rpc.benchmark.RpcBenchmarkClient > "benchmark.log" 2>&1 \ No newline at end of file diff --git a/dubbo-test/dubbo-test-benchmark-client/src/main/java/com/alibaba/dubbo/rpc/benchmark/AbstractBenchmarkClient.java b/dubbo-test/dubbo-test-benchmark-client/src/main/java/com/alibaba/dubbo/rpc/benchmark/AbstractBenchmarkClient.java new file mode 100644 index 000000000000..63dbf9783e4d --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-client/src/main/java/com/alibaba/dubbo/rpc/benchmark/AbstractBenchmarkClient.java @@ -0,0 +1,251 @@ +package com.alibaba.dubbo.rpc.benchmark; + +/** + * nfs-rpc + * Apache License + * + * http://code.google.com/p/nfs-rpc (c) 2011 + */ +import java.io.BufferedWriter; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.lang.reflect.InvocationTargetException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.CyclicBarrier; + +import com.alibaba.dubbo.common.utils.ConfigUtils; + +/** + * Abstract benchmark client,test for difference scenes Usage: -Dwrite.statistics=false BenchmarkClient serverIP + * serverPort concurrents timeout codectype requestSize runtime(seconds) clientNums + * + * @author bluedavy + */ +public abstract class AbstractBenchmarkClient { + + private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + private static long maxTPS = 0; + + private static long minTPS = 0; + + private static long allRequestSum; + + private static long allResponseTimeSum; + + private static long allErrorRequestSum; + + private static long allErrorResponseTimeSum; + + private static int runtime; + + // < 0 + private static long below0sum; + + // (0,1] + private static long above0sum; + + // (1,5] + private static long above1sum; + + // (5,10] + private static long above5sum; + + // (10,50] + private static long above10sum; + + // (50,100] + private static long above50sum; + + // (100,500] + private static long above100sum; + + // (500,1000] + private static long above500sum; + + // > 1000 + private static long above1000sum; + + Properties properties = ConfigUtils.getProperties(); + + public void run(String[] args) throws Exception { + + final String serverIP = properties.getProperty("serverip"); + final int serverPort = Integer.parseInt(properties.getProperty("serverport")); + final int concurrents = Integer.parseInt(properties.getProperty("concurrents")); + final int timeout = Integer.parseInt(properties.getProperty("timeout")); + runtime = Integer.parseInt(properties.getProperty("runtime")); + final long endtime = System.nanoTime() / 1000L + runtime * 1000 * 1000L; + final int clientNums = Integer.parseInt(properties.getProperty("connectionnums")); + final String protocol =properties.getProperty("protocol"); + final String serialization =properties.getProperty("serialization"); + + // Print start info + Date currentDate = new Date(); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(currentDate); + calendar.add(Calendar.SECOND, runtime); + StringBuilder startInfo = new StringBuilder(dateFormat.format(currentDate)); + startInfo.append(" ready to start client benchmark,server is "); + startInfo.append(serverIP).append(":").append(serverPort); + startInfo.append(",protocol is: ").append(protocol); + startInfo.append(",serialization is: ").append(serialization); + startInfo.append(",concurrents is: ").append(concurrents); + startInfo.append(",clientNums is: ").append(clientNums); + startInfo.append(",timeout is:").append(timeout); + startInfo.append(" s,the benchmark will end at:").append(dateFormat.format(calendar.getTime())); + System.out.println(startInfo.toString()); + + CyclicBarrier barrier = new CyclicBarrier(concurrents); + CountDownLatch latch = new CountDownLatch(concurrents); + List runnables = new ArrayList(); + // benchmark start after thirty seconds,let java app warm up + long beginTime = System.nanoTime() / 1000L + 30 * 1000 * 1000L; + for (int i = 0; i < concurrents; i++) { + ClientRunnable runnable = getClientRunnable(protocol, serialization, serverIP, serverPort, clientNums, timeout, barrier, latch, + beginTime, endtime); + runnables.add(runnable); + } + + startRunnables(runnables); + + latch.await(); + + // read results & add all + // key: runtime second range value: Long[2] array Long[0]: execute count Long[1]: response time sum + Map times = new HashMap(); + Map errorTimes = new HashMap(); + for (ClientRunnable runnable : runnables) { + List results = runnable.getResults(); + long[] responseSpreads = results.get(0); + below0sum += responseSpreads[0]; + above0sum += responseSpreads[1]; + above1sum += responseSpreads[2]; + above5sum += responseSpreads[3]; + above10sum += responseSpreads[4]; + above50sum += responseSpreads[5]; + above100sum += responseSpreads[6]; + above500sum += responseSpreads[7]; + above1000sum += responseSpreads[8]; + long[] tps = results.get(1); + long[] responseTimes = results.get(2); + long[] errorTPS = results.get(3); + long[] errorResponseTimes = results.get(4); + for (int i = 0; i < tps.length; i++) { + String key = String.valueOf(i); + if (times.containsKey(key)) { + Long[] successInfos = times.get(key); + Long[] errorInfos = errorTimes.get(key); + successInfos[0] += tps[i]; + successInfos[1] += responseTimes[i]; + errorInfos[0] += errorTPS[i]; + errorInfos[1] += errorResponseTimes[i]; + times.put(key, successInfos); + errorTimes.put(key, errorInfos); + } else { + Long[] successInfos = new Long[2]; + successInfos[0] = tps[i]; + successInfos[1] = responseTimes[i]; + Long[] errorInfos = new Long[2]; + errorInfos[0] = errorTPS[i]; + errorInfos[1] = errorResponseTimes[i]; + times.put(key, successInfos); + errorTimes.put(key, errorInfos); + } + } + } + + long ignoreRequest = 0; + long ignoreErrorRequest = 0; + int maxTimeRange = runtime - 30; + // ignore the last 10 second requests,so tps can count more accurate + for (int i = 0; i < 10; i++) { + Long[] values = times.remove(String.valueOf(maxTimeRange - i)); + if (values != null) { + ignoreRequest += values[0]; + } + Long[] errorValues = errorTimes.remove(String.valueOf(maxTimeRange - i)); + if (errorValues != null) { + ignoreErrorRequest += errorValues[0]; + } + } + + for (Map.Entry entry : times.entrySet()) { + long successRequest = entry.getValue()[0]; + long errorRequest = 0; + if (errorTimes.containsKey(entry.getKey())) { + errorRequest = errorTimes.get(entry.getKey())[0]; + } + allRequestSum += successRequest; + allResponseTimeSum += entry.getValue()[1]; + allErrorRequestSum += errorRequest; + if (errorTimes.containsKey(entry.getKey())) { + allErrorResponseTimeSum += errorTimes.get(entry.getKey())[1]; + } + long currentRequest = successRequest + errorRequest; + if (currentRequest > maxTPS) { + maxTPS = currentRequest; + } + if (minTPS == 0 || currentRequest < minTPS) { + minTPS = currentRequest; + } + } + + boolean isWriteResult = Boolean.parseBoolean(System.getProperty("write.statistics", "false")); + if (isWriteResult) { + BufferedWriter writer = new BufferedWriter(new FileWriter("benchmark.all.results")); + for (Map.Entry entry : times.entrySet()) { + writer.write(entry.getKey() + "," + entry.getValue()[0] + "," + entry.getValue()[1] + "\r\n"); + } + writer.close(); + } + + System.out.println("----------Benchmark Statistics--------------"); + System.out.println(" Concurrents: " + concurrents); + System.out.println(" ClientNums: " + clientNums); + System.out.println(" Runtime: " + runtime + " seconds"); + System.out.println(" Benchmark Time: " + times.keySet().size()); + long benchmarkRequest = allRequestSum + allErrorRequestSum; + long allRequest = benchmarkRequest + ignoreRequest + ignoreErrorRequest; + System.out.println(" Requests: " + allRequest + " Success: " + (allRequestSum + ignoreRequest) * 100 + / allRequest + "% (" + (allRequestSum + ignoreRequest) + ") Error: " + + (allErrorRequestSum + ignoreErrorRequest) * 100 / allRequest + "% (" + + (allErrorRequestSum + ignoreErrorRequest) + ")"); + System.out.println(" Avg TPS: " + benchmarkRequest / times.keySet().size() + " Max TPS: " + maxTPS + + " Min TPS: " + minTPS); + System.out.println(" Avg RT: " + (allErrorResponseTimeSum + allResponseTimeSum) / benchmarkRequest / 1000f + + "ms"); + System.out.println(" RT <= 0: " + (below0sum * 100 / allRequest) + "% " + below0sum + "/" + allRequest); + System.out.println(" RT (0,1]: " + (above0sum * 100 / allRequest) + "% " + above0sum + "/" + allRequest); + System.out.println(" RT (1,5]: " + (above1sum * 100 / allRequest) + "% " + above1sum + "/" + allRequest); + System.out.println(" RT (5,10]: " + (above5sum * 100 / allRequest) + "% " + above5sum + "/" + allRequest); + System.out.println(" RT (10,50]: " + (above10sum * 100 / allRequest) + "% " + above10sum + "/" + allRequest); + System.out.println(" RT (50,100]: " + (above50sum * 100 / allRequest) + "% " + above50sum + "/" + allRequest); + System.out.println(" RT (100,500]: " + (above100sum * 100 / allRequest) + "% " + above100sum + "/" + allRequest); + System.out.println(" RT (500,1000]: " + (above500sum * 100 / allRequest) + "% " + above500sum + "/" + + allRequest); + System.out.println(" RT > 1000: " + (above1000sum * 100 / allRequest) + "% " + above1000sum + "/" + allRequest); + System.exit(0); + } + + public abstract ClientRunnable getClientRunnable(String protocol, String serialization, String targetIP, int targetPort, int clientNums, int rpcTimeout, + CyclicBarrier barrier, CountDownLatch latch, long startTime, + long endTime) throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException; + + protected void startRunnables(List runnables) { + for (int i = 0; i < runnables.size(); i++) { + final ClientRunnable runnable = runnables.get(i); + Thread thread = new Thread(runnable, "benchmarkclient-" + i); + thread.start(); + } + } + +} diff --git a/dubbo-test/dubbo-test-benchmark-client/src/main/java/com/alibaba/dubbo/rpc/benchmark/AbstractClientRunnable.java b/dubbo-test/dubbo-test-benchmark-client/src/main/java/com/alibaba/dubbo/rpc/benchmark/AbstractClientRunnable.java new file mode 100644 index 000000000000..9df55a6799ed --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-client/src/main/java/com/alibaba/dubbo/rpc/benchmark/AbstractClientRunnable.java @@ -0,0 +1,176 @@ +package com.alibaba.dubbo.rpc.benchmark; + +/** + * nfs-rpc Apache License http://code.google.com/p/nfs-rpc (c) 2011 + */ +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.CyclicBarrier; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Simple Processor RPC Benchmark Client Thread + * + * @author bluedavy + */ +public abstract class AbstractClientRunnable implements ClientRunnable { + + private static final Log LOGGER = LogFactory.getLog(AbstractClientRunnable.class); + + private CyclicBarrier barrier; + + private CountDownLatch latch; + + private long endTime; + + private boolean running = true; + + // response time spread + private long[] responseSpreads = new long[9]; + + // error request per second + private long[] errorTPS = null; + + // error response times per second + private long[] errorResponseTimes = null; + + // tps per second + private long[] tps = null; + + // response times per second + private long[] responseTimes = null; + + // benchmark startTime + private long startTime; + + // benchmark maxRange + private int maxRange; + + private ServiceFactory serviceFactory = new ServiceFactory(); + + public AbstractClientRunnable(String protocol, String serialization, String targetIP, int targetPort, int clientNums, int rpcTimeout, + CyclicBarrier barrier, CountDownLatch latch, long startTime, long endTime){ + + this.barrier = barrier; + this.latch = latch; + this.startTime = startTime; + this.endTime = endTime; + serviceFactory.setProtocol(protocol); + serviceFactory.setTargetIP(targetIP); + serviceFactory.setClientNums(clientNums); + serviceFactory.setTargetPort(targetPort); + serviceFactory.setConnectTimeout(rpcTimeout); + serviceFactory.setSerialization(serialization); + maxRange = (Integer.parseInt(String.valueOf((endTime - startTime))) / 1000000) + 1; + errorTPS = new long[maxRange]; + errorResponseTimes = new long[maxRange]; + tps = new long[maxRange]; + responseTimes = new long[maxRange]; + // init + for (int i = 0; i < maxRange; i++) { + errorTPS[i] = 0; + errorResponseTimes[i] = 0; + tps[i] = 0; + responseTimes[i] = 0; + } + } + + public void run() { + try { + barrier.await(); + } catch (Exception e) { + // IGNORE + } + runJavaAndHessian(); + latch.countDown(); + } + + private void runJavaAndHessian() { + while (running) { + long beginTime = System.nanoTime() / 1000L; + if (beginTime >= endTime) { + running = false; + break; + } + try { + Object result = invoke(serviceFactory); + long currentTime = System.nanoTime() / 1000L; + if (beginTime <= startTime) { + continue; + } + long consumeTime = currentTime - beginTime; + sumResponseTimeSpread(consumeTime); + int range = Integer.parseInt(String.valueOf(beginTime - startTime)) / 1000000; + if (range >= maxRange) { + System.err.println("benchmark range exceeds maxRange,range is: " + range + ",maxRange is: " + + maxRange); + continue; + } + if (result != null) { + tps[range] = tps[range] + 1; + responseTimes[range] = responseTimes[range] + consumeTime; + } else { + LOGGER.error("server return result is null"); + errorTPS[range] = errorTPS[range] + 1; + errorResponseTimes[range] = errorResponseTimes[range] + consumeTime; + } + } catch (Exception e) { + e.printStackTrace(); + LOGGER.error("client.invokeSync error", e); + long currentTime = System.nanoTime() / 1000L; + if (beginTime <= startTime) { + continue; + } + long consumeTime = currentTime - beginTime; + sumResponseTimeSpread(consumeTime); + int range = Integer.parseInt(String.valueOf(beginTime - startTime)) / 1000000; + if (range >= maxRange) { + System.err.println("benchmark range exceeds maxRange,range is: " + range + ",maxRange is: " + + maxRange); + continue; + } + errorTPS[range] = errorTPS[range] + 1; + errorResponseTimes[range] = errorResponseTimes[range] + consumeTime; + } + } + } + + public abstract Object invoke(ServiceFactory serviceFactory); + + public List getResults() { + List results = new ArrayList(); + results.add(responseSpreads); + results.add(tps); + results.add(responseTimes); + results.add(errorTPS); + results.add(errorResponseTimes); + return results; + } + + private void sumResponseTimeSpread(long responseTime) { + responseTime = responseTime / 1000L; + if (responseTime <= 0) { + responseSpreads[0] = responseSpreads[0] + 1; + } else if (responseTime > 0 && responseTime <= 1) { + responseSpreads[1] = responseSpreads[1] + 1; + } else if (responseTime > 1 && responseTime <= 5) { + responseSpreads[2] = responseSpreads[2] + 1; + } else if (responseTime > 5 && responseTime <= 10) { + responseSpreads[3] = responseSpreads[3] + 1; + } else if (responseTime > 10 && responseTime <= 50) { + responseSpreads[4] = responseSpreads[4] + 1; + } else if (responseTime > 50 && responseTime <= 100) { + responseSpreads[5] = responseSpreads[5] + 1; + } else if (responseTime > 100 && responseTime <= 500) { + responseSpreads[6] = responseSpreads[6] + 1; + } else if (responseTime > 500 && responseTime <= 1000) { + responseSpreads[7] = responseSpreads[7] + 1; + } else if (responseTime > 1000) { + responseSpreads[8] = responseSpreads[8] + 1; + } + } + +} diff --git a/dubbo-test/dubbo-test-benchmark-client/src/main/java/com/alibaba/dubbo/rpc/benchmark/BidClientRunnable.java b/dubbo-test/dubbo-test-benchmark-client/src/main/java/com/alibaba/dubbo/rpc/benchmark/BidClientRunnable.java new file mode 100644 index 000000000000..d136543f0ce6 --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-client/src/main/java/com/alibaba/dubbo/rpc/benchmark/BidClientRunnable.java @@ -0,0 +1,64 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.benchmark; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.CyclicBarrier; + +/** + * @author lishen + */ +public class BidClientRunnable extends AbstractClientRunnable{ + + private final BidRequest request = new BidRequest(); + + public BidClientRunnable(String protocol, String serialization, String targetIP, int targetPort, int clientNums, int rpcTimeout, + CyclicBarrier barrier, CountDownLatch latch, long startTime, + long endTime){ + super(protocol, serialization, targetIP, targetPort, clientNums, rpcTimeout, barrier, latch, startTime, endTime); + Impression imp = new Impression(); + imp.setBidFloor(1.1); + imp.setId("abc"); + List imps = new ArrayList(1); + imps.add(imp); + request.setImpressions(imps); + + Geo geo = new Geo(); + geo.setCity("beijing"); + geo.setCountry("china"); + geo.setLat(100.1f); + geo.setLon(100.1f); + + Device device = new Device(); + device.setMake("apple"); + device.setOs("ios"); + device.setVersion("7.0"); + device.setLang("zh_CN"); + device.setModel("iphone"); + device.setGeo(geo); + request.setDevice(device); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public Object invoke(ServiceFactory serviceFactory) { + EchoService echoService = (EchoService) serviceFactory.get(EchoService.class); + BidRequest result = echoService.bid(request); + return result; + } +} diff --git a/dubbo-test/dubbo-test-benchmark-client/src/main/java/com/alibaba/dubbo/rpc/benchmark/ClientRunnable.java b/dubbo-test/dubbo-test-benchmark-client/src/main/java/com/alibaba/dubbo/rpc/benchmark/ClientRunnable.java new file mode 100644 index 000000000000..6710ecb02727 --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-client/src/main/java/com/alibaba/dubbo/rpc/benchmark/ClientRunnable.java @@ -0,0 +1,20 @@ +/** + * nfs-rpc + * Apache License + * + * http://code.google.com/p/nfs-rpc (c) 2011 + */ +package com.alibaba.dubbo.rpc.benchmark; + +import java.util.List; + +/** + * client runnable,so we can collect results + * + * @author bluedavy + */ +public interface ClientRunnable extends Runnable { + + public List getResults(); + +} diff --git a/dubbo-test/dubbo-test-benchmark-client/src/main/java/com/alibaba/dubbo/rpc/benchmark/RpcBenchmarkClient.java b/dubbo-test/dubbo-test-benchmark-client/src/main/java/com/alibaba/dubbo/rpc/benchmark/RpcBenchmarkClient.java new file mode 100644 index 000000000000..5972e7577525 --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-client/src/main/java/com/alibaba/dubbo/rpc/benchmark/RpcBenchmarkClient.java @@ -0,0 +1,24 @@ +package com.alibaba.dubbo.rpc.benchmark; + +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.CyclicBarrier; + +public class RpcBenchmarkClient extends AbstractBenchmarkClient { + + @SuppressWarnings("rawtypes") + @Override + public ClientRunnable getClientRunnable(String protocol, String serialization, String targetIP, int targetPort, int clientNums, int rpcTimeout, + CyclicBarrier barrier, CountDownLatch latch, long startTime, long endTime) throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { + String runnable = properties.getProperty("classname"); + Class[] parameterTypes = new Class[] { String.class, String.class, String.class, int.class, int.class, int.class, CyclicBarrier.class, + CountDownLatch.class, long.class, long.class }; + Object[] parameters = new Object[] { protocol, serialization, targetIP, targetPort, clientNums, rpcTimeout, barrier, latch, startTime, + endTime }; + return (ClientRunnable) Class.forName(runnable).getConstructor(parameterTypes).newInstance(parameters); + } + + public static void main(String[] args) throws Exception { + new RpcBenchmarkClient().run(args); + } +} diff --git a/dubbo-test/dubbo-test-benchmark-client/src/main/java/com/alibaba/dubbo/rpc/benchmark/ServiceFactory.java b/dubbo-test/dubbo-test-benchmark-client/src/main/java/com/alibaba/dubbo/rpc/benchmark/ServiceFactory.java new file mode 100644 index 000000000000..29a497ea3288 --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-client/src/main/java/com/alibaba/dubbo/rpc/benchmark/ServiceFactory.java @@ -0,0 +1,118 @@ +package com.alibaba.dubbo.rpc.benchmark; + +import java.util.concurrent.ConcurrentHashMap; + +import com.alibaba.dubbo.common.utils.StringUtils; +import com.alibaba.dubbo.config.ApplicationConfig; +import com.alibaba.dubbo.config.ReferenceConfig; + +/** + * Abstract Service Factory,create custom nums Service + * + * @author tony.chenl + */ +public class ServiceFactory { + + String targetIP = null; + + int targetPort = 0; + + int connectTimeout = 0; + + int clientNums = 0; + + String protocol; + + String serialization; + + public String getTargetIP() { + return targetIP; + } + + public void setTargetIP(String targetIP) { + this.targetIP = targetIP; + } + + public int getTargetPort() { + return targetPort; + } + + public void setTargetPort(int targetPort) { + this.targetPort = targetPort; + } + + public int getConnectTimeout() { + return connectTimeout; + } + + public void setConnectTimeout(int connectTimeout) { + this.connectTimeout = connectTimeout; + } + + public int getClientNums() { + return clientNums; + } + + public void setClientNums(int clientNums) { + this.clientNums = clientNums; + } + + public String getProtocol() { + return protocol; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public String getSerialization() { + return serialization; + } + + public void setSerialization(String serialization) { + this.serialization = serialization; + } + + // Cache ExchangeClient + private static ConcurrentHashMap services = new ConcurrentHashMap(); + + @SuppressWarnings("unchecked") + public T get(final Class cls){ + String key = cls.getName(); + if (services.containsKey(key)) { + return (T) services.get(key); + + } else { + T service = createClient(cls, targetIP, targetPort, connectTimeout,clientNums, protocol, serialization); + services.put(key, service); + return (T) services.get(key); + } + } + + protected T createClient(Class cls, String targetIP, int targetPort, int connectTimeout,int clientNums, String protocol, String serialization){ + ReferenceConfig referenceConfig = new ReferenceConfig(); + referenceConfig.setInterface(cls); + StringBuilder url = new StringBuilder(); + url.append(protocol); + url.append("://"); + url.append(targetIP); + url.append(":"); + url.append(targetPort); + url.append("/"); + url.append(cls.getName()); + url.append("?optimizer=com.alibaba.dubbo.rpc.benchmark.SerializationOptimizerImpl"); + if (!StringUtils.isEmpty(serialization)) { + url.append("&serialization="); + url.append(serialization); + } + referenceConfig.setUrl(url.toString()); + // hardcode + referenceConfig.setConnections(clientNums); + ApplicationConfig application = new ApplicationConfig(); + application.setName("dubbo_consumer"); + referenceConfig.setApplication(application); + referenceConfig.setTimeout(connectTimeout); + return referenceConfig.get(); + } + +} diff --git a/dubbo-test/dubbo-test-benchmark-client/src/main/java/com/alibaba/dubbo/rpc/benchmark/TextClientRunnable.java b/dubbo-test/dubbo-test-benchmark-client/src/main/java/com/alibaba/dubbo/rpc/benchmark/TextClientRunnable.java new file mode 100644 index 000000000000..923e885825d1 --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-client/src/main/java/com/alibaba/dubbo/rpc/benchmark/TextClientRunnable.java @@ -0,0 +1,46 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.benchmark; + +import org.apache.commons.lang.StringUtils; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.CyclicBarrier; + +/** + * @author lishen + */ +public class TextClientRunnable extends AbstractClientRunnable{ + + private final Text text = new Text(StringUtils.leftPad("", 50000)); + + public TextClientRunnable(String protocol, String serialization, String targetIP, int targetPort, int clientNums, int rpcTimeout, + CyclicBarrier barrier, CountDownLatch latch, long startTime, + long endTime){ + super(protocol, serialization, targetIP, targetPort, clientNums, rpcTimeout, barrier, latch, startTime, endTime); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public Object invoke(ServiceFactory serviceFactory) { + EchoService echoService = (EchoService) serviceFactory.get(EchoService.class); + return echoService.text(text); + } +// +// public static void main(String[] args) { +// System.out.println( StringUtils.leftPad("", 1000).getBytes().length); +// } +} diff --git a/dubbo-test/dubbo-test-benchmark-client/src/main/resources/META-INF/cxf/org.apache.cxf.Logger b/dubbo-test/dubbo-test-benchmark-client/src/main/resources/META-INF/cxf/org.apache.cxf.Logger new file mode 100644 index 000000000000..be0c538174cb --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-client/src/main/resources/META-INF/cxf/org.apache.cxf.Logger @@ -0,0 +1 @@ +org.apache.cxf.common.logging.Log4jLogger \ No newline at end of file diff --git a/dubbo-test/dubbo-test-benchmark-client/src/main/resources/dubbo.properties b/dubbo-test/dubbo-test-benchmark-client/src/main/resources/dubbo.properties new file mode 100644 index 000000000000..f28a602c6928 --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-client/src/main/resources/dubbo.properties @@ -0,0 +1,30 @@ +serverip=127.0.0.1 +concurrents=10 +timeout=3000 +runtime=300 +connectionnums=10 + +classname=com.alibaba.dubbo.rpc.benchmark.BidClientRunnable +#classname=com.alibaba.dubbo.rpc.benchmark.TextClientRunnable + +protocol=rest +serverport=8888 + +#protocol=dubbo +#serverport=20880 +#serialization=kryo + +#protocol=webservice +#serverport=8892 + +#protocol=http +#serverport=8889 + +#protocol=hessian +#serverport=8890 + +#protocol=rmi +#serverport=8893 + + + diff --git a/dubbo-test/dubbo-test-benchmark-client/src/main/resources/log4j.xml b/dubbo-test/dubbo-test-benchmark-client/src/main/resources/log4j.xml new file mode 100644 index 000000000000..cd275123fd4c --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-client/src/main/resources/log4j.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-test/dubbo-test-benchmark-server/pom.xml b/dubbo-test/dubbo-test-benchmark-server/pom.xml new file mode 100644 index 000000000000..9a97c7df23f4 --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-server/pom.xml @@ -0,0 +1,195 @@ + + + 4.0.0 + + com.alibaba + dubbo-test + 2.8.4 + + dubbo-test-benchmark-server + jar + ${project.artifactId} + The benchmark test module of dubbo project + + true + + + + com.alibaba + dubbo + ${project.parent.version} + + + com.alibaba + dubbo-test-benchmark-api + ${project.parent.version} + + + org.javassist + javassist + + + io.netty + netty + + + org.apache.mina + mina-core + + + org.glassfish.grizzly + grizzly-core + + + org.apache.httpcomponents + httpclient + + + com.alibaba + fastjson + + + com.thoughtworks.xstream + xstream + + + org.apache.bsf + bsf-api + + + org.apache.zookeeper + zookeeper + + + com.github.sgroschupf + zkclient + + + org.apache.curator + curator-framework + + + com.googlecode.xmemcached + xmemcached + + + org.apache.cxf + cxf-rt-frontend-simple + + + org.apache.cxf + cxf-rt-transports-http + + + org.apache.thrift + libthrift + + + com.caucho + hessian + + + javax.servlet + javax.servlet-api + + + org.mortbay.jetty + jetty + + + log4j + log4j + + + org.slf4j + slf4j-api + + + redis.clients + jedis + + + javax.validation + validation-api + + + org.hibernate + hibernate-validator + + + javax.cache + cache-api + + + javax.ws.rs + javax.ws.rs-api + 2.0 + + + + + + + src/main/resources + + **/*.* + + + + + + maven-dependency-plugin + + + unpack + package + + unpack + + + + + com.alibaba + dubbo + ${project.parent.version} + ${project.build.directory}/dubbo + META-INF/assembly/** + + + + + + + + maven-assembly-plugin + + src/assembly/assembly.xml + + + + make-assembly + package + + single + + + + + + + \ No newline at end of file diff --git a/dubbo-test/dubbo-test-benchmark-server/src/assembly/assembly.xml b/dubbo-test/dubbo-test-benchmark-server/src/assembly/assembly.xml new file mode 100644 index 000000000000..674a2dc869ad --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-server/src/assembly/assembly.xml @@ -0,0 +1,23 @@ + + assembly + + tar.gz + + true + + + src/cli + / + 0755 + + + src/main/resources + conf + + + + + lib + + + \ No newline at end of file diff --git a/dubbo-test/dubbo-test-benchmark-server/src/cli/run.bat b/dubbo-test/dubbo-test-benchmark-server/src/cli/run.bat new file mode 100644 index 000000000000..0d4c7b031f12 --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-server/src/cli/run.bat @@ -0,0 +1 @@ +java -Xms1g -Xmx1g -XX:PermSize=64M -XX:+UseConcMarkSweepGC -Djava.ext.dirs=lib -classpath conf com.alibaba.dubbo.container.Main > benchmark.log \ No newline at end of file diff --git a/dubbo-test/dubbo-test-benchmark-server/src/cli/run.sh b/dubbo-test/dubbo-test-benchmark-server/src/cli/run.sh new file mode 100644 index 000000000000..30d00abd10fb --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-server/src/cli/run.sh @@ -0,0 +1 @@ +java -Xms1g -Xmx1g -XX:PermSize=64M -XX:+UseConcMarkSweepGC -Djava.ext.dirs=./lib -classpath conf com.alibaba.dubbo.container.Main > "benchmark.log" 2>&1 \ No newline at end of file diff --git a/dubbo-test/dubbo-test-benchmark-server/src/main/java/com/alibaba/dubbo/rpc/benchmark/EchoServiceImpl.java b/dubbo-test/dubbo-test-benchmark-server/src/main/java/com/alibaba/dubbo/rpc/benchmark/EchoServiceImpl.java new file mode 100644 index 000000000000..5ae5810d69b2 --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-server/src/main/java/com/alibaba/dubbo/rpc/benchmark/EchoServiceImpl.java @@ -0,0 +1,41 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.benchmark; + +public class EchoServiceImpl implements EchoService { + +// private final BidResponse response = new BidResponse(); + + public EchoServiceImpl() { +// response.setId("abc"); +// +// SeatBid seatBid = new SeatBid(); +// seatBid.setGroup("group"); +// seatBid.setSeat("seat"); +// List seatBids = new ArrayList(1); +// seatBids.add(seatBid); +// +// response.setSeatBids(seatBids); + } + + public BidRequest bid(BidRequest request) { + return request; + } + + public Text text(Text text) { + return text; + } +} \ No newline at end of file diff --git a/dubbo-test/dubbo-test-benchmark-server/src/main/java/com/alibaba/dubbo/rpc/benchmark/Main.java b/dubbo-test/dubbo-test-benchmark-server/src/main/java/com/alibaba/dubbo/rpc/benchmark/Main.java new file mode 100644 index 000000000000..786d1b067b0b --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-server/src/main/java/com/alibaba/dubbo/rpc/benchmark/Main.java @@ -0,0 +1,24 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.benchmark; + +public class Main { + + public static void main(String[] args) { + com.alibaba.dubbo.container.Main.main(args); + } + +} \ No newline at end of file diff --git a/dubbo-test/dubbo-test-benchmark-server/src/main/resources/META-INF/cxf/org.apache.cxf.Logger b/dubbo-test/dubbo-test-benchmark-server/src/main/resources/META-INF/cxf/org.apache.cxf.Logger new file mode 100644 index 000000000000..be0c538174cb --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-server/src/main/resources/META-INF/cxf/org.apache.cxf.Logger @@ -0,0 +1 @@ +org.apache.cxf.common.logging.Log4jLogger \ No newline at end of file diff --git a/dubbo-test/dubbo-test-benchmark-server/src/main/resources/META-INF/spring/dubbo-provider.xml b/dubbo-test/dubbo-test-benchmark-server/src/main/resources/META-INF/spring/dubbo-provider.xml new file mode 100644 index 000000000000..ada9b4d5cd3f --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-server/src/main/resources/META-INF/spring/dubbo-provider.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-test/dubbo-test-benchmark-server/src/main/resources/log4j.xml b/dubbo-test/dubbo-test-benchmark-server/src/main/resources/log4j.xml new file mode 100644 index 000000000000..cd275123fd4c --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-server/src/main/resources/log4j.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-test/dubbo-test-benchmark-server/src/main/webapp/WEB-INF/web.xml b/dubbo-test/dubbo-test-benchmark-server/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000000..2a2f3a6cead4 --- /dev/null +++ b/dubbo-test/dubbo-test-benchmark-server/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,30 @@ + + + + + + contextConfigLocation + /WEB-INF/classes/META-INF/spring/dubbo-provider.xml + + + + + com.alibaba.dubbo.remoting.http.servlet.BootstrapListener + + + + org.springframework.web.context.ContextLoaderListener + + + + dispatcher + com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet + 1 + + + + dispatcher + /* + + \ No newline at end of file diff --git a/dubbo-test/dubbo-test-benchmark/pom.xml b/dubbo-test/dubbo-test-benchmark/pom.xml index e3cbae28abce..2593c9e50547 100644 --- a/dubbo-test/dubbo-test-benchmark/pom.xml +++ b/dubbo-test/dubbo-test-benchmark/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-test - 2.4.3 + 2.8.4 dubbo-test-benchmark jar diff --git a/dubbo-test/dubbo-test-benchmark/src/main/resources/ReadMe.txt b/dubbo-test/dubbo-test-benchmark/src/main/resources/ReadMe.txt index 88cc032dd362..5d695e4a804f 100644 --- a/dubbo-test/dubbo-test-benchmark/src/main/resources/ReadMe.txt +++ b/dubbo-test/dubbo-test-benchmark/src/main/resources/ReadMe.txt @@ -1,13 +1,13 @@ -һ½һbenchmarḳdemo.benchmark -ԼĽӿapidubbo.benchmark.jar(ѹdubbo.benchmark.tar.gzlibĿ¼) -½һ࣬ʵAbstractClientRunnable - aʵָĹ캯 - bʵinvokeͨserviceFactoryؽӿڴʵԼҵ߼ - public Object invoke(ServiceFactory serviceFactory) { +一、新建一个benchmark工程,如demo.benchmark +二、导入自己服务的接口api包和dubbo.benchmark.jar(解压dubbo.benchmark.tar.gz,在lib目录下) +三、新建一个类,实现AbstractClientRunnable + a、实现父类的构造函数 + b、实现invoke方法,通过serviceFactory创建本地接口代理,并实现自己的业务逻辑,如下 + public Object invoke(ServiceFactory serviceFactory) { DemoService demoService = (DemoService) serviceFactory.get(DemoService.class); return demoService.sendRequest("hello"); } -ġԼbenchmark̴jar,demo.benchmark.jar -塢demo.benchmark.jarŵdubbo.benchmark/libĿ¼ -duubo.properties -ߡrun.bat(windows)run.sh(linux) \ No newline at end of file +四、将自己的benchmark工程打成jar包,如demo.benchmark.jar +五、将demo.benchmark.jar放到dubbo.benchmark/lib目录下 +六、配置dubbo.properties +七、运行run.bat(windows)或run.sh(linux) \ No newline at end of file diff --git a/dubbo-test/dubbo-test-compatibility/pom.xml b/dubbo-test/dubbo-test-compatibility/pom.xml index 1ebfe3a3f369..d02370e64cc7 100644 --- a/dubbo-test/dubbo-test-compatibility/pom.xml +++ b/dubbo-test/dubbo-test-compatibility/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-test - 2.4.3 + 2.8.4 dubbo-test-compatibility jar diff --git a/dubbo-test/dubbo-test-examples/pom.xml b/dubbo-test/dubbo-test-examples/pom.xml index 5bad7f5dc825..43b4b699291e 100644 --- a/dubbo-test/dubbo-test-examples/pom.xml +++ b/dubbo-test/dubbo-test-examples/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-test - 2.4.3 + 2.8.4 dubbo-test-examples jar @@ -137,6 +137,30 @@ org.hibernate hibernate-validator + + com.alibaba + fastjson + + + joda-time + joda-time + 2.4 + + + com.fasterxml.jackson.datatype + jackson-datatype-joda + 2.4.0 + + + org.springframework + spring-aop + + + + org.aspectj + aspectjweaver + 1.7.4 + diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/AopAnnotationConsumer.java b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/AopAnnotationConsumer.java new file mode 100644 index 000000000000..be5a4d04f3cb --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/AopAnnotationConsumer.java @@ -0,0 +1,36 @@ +/* + * Copyright 1999-2012 Alibaba Group. + * + * Licensed 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.examples.aop; + +import com.alibaba.dubbo.examples.aop.action.AopAnnotationAction; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * @author dylan + */ +public class AopAnnotationConsumer { + + public static void main(String[] args) throws Exception { + String config = AopAnnotationConsumer.class.getPackage().getName().replace('.', '/') + "/annotation-consumer.xml"; + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(config); + context.start(); + final AopAnnotationAction annotationAction = (AopAnnotationAction)context.getBean("aopAnnotationAction"); + String hello = annotationAction.doSayHello("world"); + System.out.println("result :" + hello); + System.in.read(); + } + +} diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/AopAnnotationProvider.java b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/AopAnnotationProvider.java new file mode 100644 index 000000000000..9a9542a34ae2 --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/AopAnnotationProvider.java @@ -0,0 +1,32 @@ +/* + * Copyright 1999-2012 Alibaba Group. + * + * Licensed 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.examples.aop; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * @author dylan + */ +public class AopAnnotationProvider { + + public static void main(String[] args) throws Exception { + String config = AopAnnotationProvider.class.getPackage().getName().replace('.', '/') + "/annotation-provider.xml"; + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(config); + context.start(); + System.in.read(); + } + +} diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/action/AopAnnotationAction.java b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/action/AopAnnotationAction.java new file mode 100644 index 000000000000..52a4ed20b072 --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/action/AopAnnotationAction.java @@ -0,0 +1,35 @@ +/* + * Copyright 1999-2012 Alibaba Group. + * + * Licensed 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.examples.aop.action; + +import com.alibaba.dubbo.config.annotation.Reference; +import com.alibaba.dubbo.examples.aop.api.AopAnnotationService; +import org.springframework.stereotype.Component; + +/** + * @author dylan + */ +@Component("aopAnnotationAction") +public class AopAnnotationAction { + + @Reference + private AopAnnotationService annotationService; + + public String doSayHello(String name) { + return annotationService.sayHello(name); + } + +} diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/annotation-consumer.xml b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/annotation-consumer.xml new file mode 100644 index 000000000000..6eb4da393615 --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/annotation-consumer.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/annotation-provider.xml b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/annotation-provider.xml new file mode 100644 index 000000000000..9dfaf32445df --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/annotation-provider.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/aop-aspect.xml b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/aop-aspect.xml new file mode 100644 index 000000000000..8061f37f73b3 --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/aop-aspect.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/api/AopAnnotationService.java b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/api/AopAnnotationService.java new file mode 100644 index 000000000000..60e6cefc3033 --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/api/AopAnnotationService.java @@ -0,0 +1,25 @@ +/* + * Copyright 1999-2012 Alibaba Group. + * + * Licensed 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.examples.aop.api; + +/** + * @author dylan + */ +public interface AopAnnotationService { + + String sayHello(String name); + +} diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/aspect/AnnotationAspect.java b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/aspect/AnnotationAspect.java new file mode 100644 index 000000000000..5fb0743599d7 --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/aspect/AnnotationAspect.java @@ -0,0 +1,11 @@ +package com.alibaba.dubbo.examples.aop.aspect; + +/** + * @author dylan + */ +public class AnnotationAspect { + + public void before(){ + System.out.println("aspect before------------"); + } +} diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/impl/AopAnnotationServiceImpl.java b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/impl/AopAnnotationServiceImpl.java new file mode 100644 index 000000000000..71440f6ee3e3 --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/aop/impl/AopAnnotationServiceImpl.java @@ -0,0 +1,32 @@ +/* + * Copyright 1999-2012 Alibaba Group. + * + * Licensed 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.examples.aop.impl; + +import com.alibaba.dubbo.config.annotation.Service; +import com.alibaba.dubbo.examples.aop.api.AopAnnotationService; + +/** + * @author dylan + */ +@Service +public class AopAnnotationServiceImpl implements AopAnnotationService { + + public String sayHello(String name) { + System.out.println("aop provider received: " + name); + return "aop annotation: hello, " + name; + } + +} \ No newline at end of file diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/JacksonConsumer.java b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/JacksonConsumer.java new file mode 100644 index 000000000000..e13847d690d7 --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/JacksonConsumer.java @@ -0,0 +1,67 @@ +/* + * Copyright 1999-2012 Alibaba Group. + * + * Licensed 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.examples.jackson; + +import com.alibaba.dubbo.examples.jackson.api.*; +import com.google.common.collect.Lists; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import java.util.Arrays; +import java.util.List; + +/** + * JacksonConsumer + * + * @author dylan + */ +public class JacksonConsumer { + + public static void main(String[] args) throws Exception { + String config = JacksonConsumer.class.getPackage().getName().replace('.', '/') + "/jackson-consumer.xml"; + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(config); + context.start(); + JacksonService jacksonService = (JacksonService) context.getBean("jacksonService"); + System.out.println("TEST: sayHello"); + String hello = jacksonService.sayHello("world"); + System.out.println(hello); + + System.out.println("TEST: testJacksonBean"); + JacksonBean jacksonBean = jacksonService.testJacksonBean(new JacksonBean(), new JacksonInnerBean()); + System.out.println(jacksonBean); + + System.out.println("TEST: testInheritBean"); + Inherit inherit = jacksonService.testInheritBean(new InheritBean(), new JacksonBean()); + System.out.println(inherit); + + System.out.println("TEST: testArray"); + int[] intArray = jacksonService.testArray(new int[]{1,2}); + System.out.println(Arrays.toString(intArray)); + + System.out.println("TEST: testBeanArray"); + JacksonBean[] beanArray = jacksonService.testBeanArray(new JacksonBean[]{new JacksonBean(), new JacksonBean()}); + System.out.println(Arrays.toString(beanArray)); + + System.out.println("TEST: testException"); + try { + jacksonService.testException(); + } catch(Exception e){ + System.out.println("exception : " + e.getClass() + " : " + e.getMessage()); + } + + System.in.read(); + } + +} diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/JacksonProvider.java b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/JacksonProvider.java new file mode 100644 index 000000000000..dfa097fce184 --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/JacksonProvider.java @@ -0,0 +1,34 @@ +/* + * Copyright 1999-2012 Alibaba Group. + * + * Licensed 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.examples.jackson; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * JacksonProvider + * + * @author dylan + */ +public class JacksonProvider { + + public static void main(String[] args) throws Exception { + String config = JacksonProvider.class.getPackage().getName().replace('.', '/') + "/jackson-provider.xml"; + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(config); + context.start(); + System.in.read(); + } + +} diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/api/AbstractInheritBean.java b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/api/AbstractInheritBean.java new file mode 100644 index 000000000000..70ee7e17eb4e --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/api/AbstractInheritBean.java @@ -0,0 +1,33 @@ +package com.alibaba.dubbo.examples.jackson.api; + +/** + * Created by dylan on 14-11-22. + */ +public abstract class AbstractInheritBean implements Inherit{ + private String username = "Dylan"; + private int age = 10; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + @Override + public String toString() { + return "AbstractInheritBean{" + + "username='" + username + '\'' + + ", age=" + age + + '}'; + } +} diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/api/Inherit.java b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/api/Inherit.java new file mode 100644 index 000000000000..e57b13bba989 --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/api/Inherit.java @@ -0,0 +1,7 @@ +package com.alibaba.dubbo.examples.jackson.api; + +/** + * Created by dylan on 14-11-22. + */ +public interface Inherit { +} diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/api/InheritBean.java b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/api/InheritBean.java new file mode 100644 index 000000000000..6bccb8e909c4 --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/api/InheritBean.java @@ -0,0 +1,35 @@ +package com.alibaba.dubbo.examples.jackson.api; + +import java.util.Date; + +/** + * Created by dylan on 14-11-22. + */ +public class InheritBean extends AbstractInheritBean { + private String address = "ShangHai"; + private Date birthDate = new Date(); + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public Date getBirthDate() { + return birthDate; + } + + public void setBirthDate(Date birthDate) { + this.birthDate = birthDate; + } + + @Override + public String toString() { + return "InheritBean{" + + "address='" + address + '\'' + + ", birthDate=" + birthDate + + "} " + super.toString(); + } +} diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/api/InheritBean2.java b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/api/InheritBean2.java new file mode 100644 index 000000000000..4bd51b074c5f --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/api/InheritBean2.java @@ -0,0 +1,25 @@ +package com.alibaba.dubbo.examples.jackson.api; + +import org.joda.time.DateTime; + +/** + * Created by dylan on 14-11-22. + */ +public class InheritBean2 extends AbstractInheritBean { + private String zipCode = "200000"; + + public String getZipCode() { + return zipCode; + } + + public void setZipCode(String zipCode) { + this.zipCode = zipCode; + } + + @Override + public String toString() { + return "InheritBean2{" + + "zipCode='" + zipCode + '\'' + + "} " + super.toString(); + } +} diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/api/JacksonBean.java b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/api/JacksonBean.java new file mode 100644 index 000000000000..f42ec8121056 --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/api/JacksonBean.java @@ -0,0 +1,110 @@ +package com.alibaba.dubbo.examples.jackson.api; + +import org.joda.time.DateTime; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +/** + * Created by dylan on 11/15/14. + */ +public class JacksonBean { + + private boolean bValue = true; + private String sValue = "string"; + private int iValue = 20; + private double dValue = 20.5; + private float fValue = 2.18f; + private long lValue = 3; + private Double dValue2 = null; + private Date date = Calendar.getInstance().getTime(); + private DateTime dateTime = DateTime.now(); + private List innerBeanList = new ArrayList(); + + public JacksonBean(){ + innerBeanList.add(new JacksonInnerBean()); + innerBeanList.add(new JacksonInnerBean()); + } + + @Override + public String toString() { + return "JacksonBean{" + + "bValue=" + bValue + + ", sValue='" + sValue + '\'' + + ", iValue=" + iValue + + ", dValue=" + dValue + + ", fValue=" + fValue + + ", lValue=" + lValue + + ", dValue2=" + dValue2 + + ", date=" + date + + ", dateTime=" + dateTime + + ", innerBeanList=" + innerBeanList + + '}'; + } + + public boolean isbValue() { + return bValue; + } + + public void setbValue(boolean bValue) { + this.bValue = bValue; + } + + public String getsValue() { + return sValue; + } + + public void setsValue(String sValue) { + this.sValue = sValue; + } + + public int getiValue() { + return iValue; + } + + public void setiValue(int iValue) { + this.iValue = iValue; + } + + public double getdValue() { + return dValue; + } + + public void setdValue(double dValue) { + this.dValue = dValue; + } + + public float getfValue() { + return fValue; + } + + public void setfValue(float fValue) { + this.fValue = fValue; + } + + public long getlValue() { + return lValue; + } + + public void setlValue(long lValue) { + this.lValue = lValue; + } + + public Double getdValue2() { + return dValue2; + } + + public void setdValue2(Double dValue2) { + this.dValue2 = dValue2; + } + + public List getInnerBeanList() { + return innerBeanList; + } + + public void setInnerBeanList(List innerBeanList) { + this.innerBeanList = innerBeanList; + } +} diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/api/JacksonInnerBean.java b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/api/JacksonInnerBean.java new file mode 100644 index 000000000000..1a44907c8d0f --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/api/JacksonInnerBean.java @@ -0,0 +1,33 @@ +package com.alibaba.dubbo.examples.jackson.api; + +/** + * Created by dylan on 11/15/14. + */ +public class JacksonInnerBean { + private String siValue = "innerStr"; + private int iiValue = 18; + + public String getSiValue() { + return siValue; + } + + public void setSiValue(String siValue) { + this.siValue = siValue; + } + + public int getIiValue() { + return iiValue; + } + + public void setIiValue(int iiValue) { + this.iiValue = iiValue; + } + + @Override + public String toString() { + return "InnerBean{" + + "siValue='" + siValue + '\'' + + ", iiValue=" + iiValue + + '}'; + } +} diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/api/JacksonService.java b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/api/JacksonService.java new file mode 100644 index 000000000000..836eb8e3b7ff --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/api/JacksonService.java @@ -0,0 +1,34 @@ +/** + * Project: dubbo-examples + * + * File Created at 2012-2-17 + * $Id$ + * + * Copyright 1999-2100 Alibaba.com Corporation Limited. + * All rights reserved. + * + * This software is the confidential and proprietary information of + * Alibaba Company. ("Confidential Information"). You shall not + * disclose such Confidential Information and shall use it only in + * accordance with the terms of the license agreement you entered into + * with Alibaba.com. + */ +package com.alibaba.dubbo.examples.jackson.api; + +/** + * @author william.liangf + */ +public interface JacksonService { + + String sayHello(String name); + + public JacksonBean testJacksonBean(JacksonBean jacksonBean, JacksonInnerBean jacksonInnerBean); + + public Inherit testInheritBean(Inherit inherit, JacksonBean jacksonBean); + + public int[] testArray(int[] array); + + public JacksonBean[] testBeanArray(JacksonBean[] jacksonBeans); + + public void testException(); +} diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/impl/JacksonServiceImpl.java b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/impl/JacksonServiceImpl.java new file mode 100644 index 000000000000..f13528bc8ba3 --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/impl/JacksonServiceImpl.java @@ -0,0 +1,64 @@ +/** + * Project: dubbo-examples + * + * File Created at 2012-2-17 + * $Id$ + * + * Copyright 1999-2100 Alibaba.com Corporation Limited. + * All rights reserved. + * + * This software is the confidential and proprietary information of + * Alibaba Company. ("Confidential Information"). You shall not + * disclose such Confidential Information and shall use it only in + * accordance with the terms of the license agreement you entered into + * with Alibaba.com. + */ +package com.alibaba.dubbo.examples.jackson.impl; + +import com.alibaba.dubbo.examples.jackson.api.*; + +/** + * @author william.liangf + */ +public class JacksonServiceImpl implements JacksonService { + + public String sayHello(String name) { + return "hello, " + name; + } + + @Override + public JacksonBean testJacksonBean(JacksonBean jacksonBean, JacksonInnerBean jacksonInnerBean) { + System.out.println(jacksonBean); + System.out.println(jacksonInnerBean); + jacksonBean.getInnerBeanList().add(jacksonInnerBean); + return jacksonBean; + } + + @Override + public Inherit testInheritBean(Inherit inherit, JacksonBean jacksonBean) { + System.out.println(inherit); + System.out.println(jacksonBean); + return new InheritBean2(); + } + + @Override + public int[] testArray(int[] array) { + return new int[]{3, 4}; + } + + @Override + public JacksonBean[] testBeanArray(JacksonBean[] jacksonBeans) { + System.out.println("testBeanArray"); + for (JacksonBean in : jacksonBeans) { + System.out.println(in); + } + return new JacksonBean[]{ + new JacksonBean(), new JacksonBean() + }; + } + + @Override + public void testException() { + throw new RuntimeException("exception from provider"); + } +} diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/jackson-consumer.xml b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/jackson-consumer.xml new file mode 100644 index 000000000000..f4a05eb5ac39 --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/jackson-consumer.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/jackson-provider.xml b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/jackson-provider.xml new file mode 100644 index 000000000000..93a9d2a6212b --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/jackson-provider.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/jacksonprovider/CustomJacksonObjectMapperProvider.java b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/jacksonprovider/CustomJacksonObjectMapperProvider.java new file mode 100644 index 000000000000..b6f1c2de4d22 --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/jackson/jacksonprovider/CustomJacksonObjectMapperProvider.java @@ -0,0 +1,15 @@ +package com.alibaba.dubbo.examples.jackson.jacksonprovider; + +import com.alibaba.dubbo.common.json.JacksonObjectMapperProvider; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Created by dylan on 11/15/14. + */ +public class CustomJacksonObjectMapperProvider implements JacksonObjectMapperProvider { + @Override + public ObjectMapper getObjectMapper() { + System.out.println("get object mapper from CustomJacksonObjectMapperProvider"); + return new ObjectMapper(); + } +} diff --git a/dubbo-test/dubbo-test-examples/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.common.json.JacksonObjectMapperProvider b/dubbo-test/dubbo-test-examples/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.common.json.JacksonObjectMapperProvider new file mode 100644 index 000000000000..b14abca92d2a --- /dev/null +++ b/dubbo-test/dubbo-test-examples/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.common.json.JacksonObjectMapperProvider @@ -0,0 +1 @@ +default=com.alibaba.dubbo.examples.jackson.jacksonprovider.CustomJacksonObjectMapperProvider \ No newline at end of file diff --git a/dubbo-test/dubbo-test-integration/pom.xml b/dubbo-test/dubbo-test-integration/pom.xml index f60e09580000..cbf43a6836a1 100644 --- a/dubbo-test/dubbo-test-integration/pom.xml +++ b/dubbo-test/dubbo-test-integration/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-test - 2.4.3 + 2.8.4 dubbo-test-integration jar diff --git a/dubbo-test/pom.xml b/dubbo-test/pom.xml index f40261af56e2..8ccfec26d319 100644 --- a/dubbo-test/pom.xml +++ b/dubbo-test/pom.xml @@ -19,7 +19,7 @@ com.alibaba dubbo-parent - 2.4.3 + 2.8.4 dubbo-test pom @@ -32,6 +32,9 @@ dubbo-test-benchmark dubbo-test-compatibility dubbo-test-integration - dubbo-test-examples + dubbo-test-examples + dubbo-test-benchmark-api + dubbo-test-benchmark-server + dubbo-test-benchmark-client diff --git a/dubbo-tool/dubbo-demo-lite-archetype/pom.xml b/dubbo-tool/dubbo-demo-lite-archetype/pom.xml new file mode 100644 index 000000000000..844d9844dbd3 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite-archetype/pom.xml @@ -0,0 +1,114 @@ + + + 4.0.0 + + com.alibaba + dubbo-demo-lite-archetype + 2.8.4 + maven-archetype + + dubbo-demo-lite-archetype + + + + + org.apache.maven.archetype + archetype-packaging + 2.2 + + + + + + + maven-archetype-plugin + 2.2 + + + + + + The demo lite module of dubbo project + + http://code.alibabatech.com/wiki/display/dubbo/dubbo-demo-lite + + + + shawn.qianx + QianXiao(Shawn) + shawn.qianx (AT) alibaba-inc.com + + Developer + + +8 + + + william.liangf + LiangFei(William) + william.liangf (AT) alibaba-inc.com + + Developer + + +8 + + + ding.lid + LiDing(Jerry) + ding.lid (AT) alibaba-inc.com + + Developer + + +8 + + + chao.liuc + LiuChao(Charles) + chao.liuc (AT) alibaba-inc.com + + Developer + + +8 + + + haoming.liuhm + LiuHaoMin(Ludvik) + haoming.liuhm (AT) alibaba-inc.com + + Developer + + +8 + + + tony.chenl + ChenLei(Tony) + tony.chenl (AT) alibaba-inc.com + + Developer + + +8 + + + gang.lvg + LvGang(Kimi) + gang.lvg (AT) alibaba-inc.com + + Developer + + +8 + + + + + + Apache 2 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + A business-friendly OSS license + + + + + scm:svn:http://code.alibabatech.com/svn/dubbo/trunk/dubbo-demo-lite + http://code.alibabatech.com/svn/dubbo/trunk/dubbo-demo-lite + + diff --git a/dubbo-tool/dubbo-demo-lite-archetype/readme.md b/dubbo-tool/dubbo-demo-lite-archetype/readme.md new file mode 100644 index 000000000000..0d5494bc0b3a --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite-archetype/readme.md @@ -0,0 +1,86 @@ +目的: +快速的使用 maven archetype 进行 dubbox rest 项目工程搭建。 +本处默认从 dubbo-demo-lite 构建一个 rest 版本的 dubbox 框架结构。 + +命令参考: + +1. 从一个已有的项目中构建一个 maven archetype, +$ mvn archetype:create-from-project -Darchetype.filteredExtentions=java,xml,jsp,properties,sql + +2. 然后再修改模板中的文件,并执行 +$ mvn clean install + +3. 开始从一个已有的 maven archetype 中复制项目 +$ mkdir tmp +$ cd tmp +$ mvn archetype:generate -DarchetypeCatalog=local + +更多资料请参考 +http://maven.apache.org/archetype/maven-archetype-plugin/examples/create-multi-module-project.html + + +使用示例列举: + +
+kangfoo@kangfoo-dk:~/work/hawkeye/tmp$ mvn archetype:generate -DarchetypeCatalog=local
+[INFO] Scanning for projects...
+[INFO]
+[INFO] ------------------------------------------------------------------------
+[INFO] Building Maven Stub Project (No POM) 1
+[INFO] ------------------------------------------------------------------------
+[INFO]
+[INFO] >>> maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom >>>
+[INFO]
+[INFO] <<< maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom <<<
+[INFO]
+[INFO] --- maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom ---
+[INFO] Generating project in Interactive mode
+[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)
+Choose archetype:
+1: local -> com.alibaba:dubbo-demo-lite-archetype (The demo lite module of dubbo project)
+Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): : 1
+Define value for property 'groupId': : com.tima
+Define value for property 'artifactId': : test3
+Define value for property 'version':  1.0-SNAPSHOT: :
+Define value for property 'package':  com.tima: : com.tima.test3
+Confirm properties configuration:
+groupId: com.tima
+artifactId: test3
+version: 1.0-SNAPSHOT
+package: com.tima.test3
+ Y: : Y
+[INFO] ----------------------------------------------------------------------------
+[INFO] Using following parameters for creating project from Archetype: dubbo-demo-lite-archetype:2.8.3
+[INFO] ----------------------------------------------------------------------------
+[INFO] Parameter: groupId, Value: com.tima
+[INFO] Parameter: artifactId, Value: test3
+[INFO] Parameter: version, Value: 1.0-SNAPSHOT
+[INFO] Parameter: package, Value: com.tima.test3
+[INFO] Parameter: packageInPathFormat, Value: com/tima/test3
+[INFO] Parameter: package, Value: com.tima.test3
+[INFO] Parameter: version, Value: 1.0-SNAPSHOT
+[INFO] Parameter: groupId, Value: com.tima
+[INFO] Parameter: artifactId, Value: test3
+[INFO] Parent element not overwritten in /home/kangfoo/work/hawkeye/tmp/test3/test3-api/pom.xml
+[INFO] Parent element not overwritten in /home/kangfoo/work/hawkeye/tmp/test3/test3-provider/pom.xml
+[INFO] Parent element not overwritten in /home/kangfoo/work/hawkeye/tmp/test3/test3-consumer/pom.xml
+[INFO] project created from Archetype in dir: /home/kangfoo/work/hawkeye/tmp/test3
+[INFO] ------------------------------------------------------------------------
+[INFO] BUILD SUCCESS
+[INFO] ------------------------------------------------------------------------
+[INFO] Total time: 27.023s
+[INFO] Finished at: Fri Dec 12 14:49:00 CST 2014
+[INFO] Final Memory: 12M/105M
+[INFO] ------------------------------------------------------------------------
+kangfoo@kangfoo-dk:~/work/hawkeye/tmp$ cd test3/
+kangfoo@kangfoo-dk:~/work/hawkeye/tmp/test3$ ll
+总用量 24
+drwxrwxr-x 5 kangfoo kangfoo 4096 12月 12 14:49 ./
+drwxrwxr-x 4 kangfoo kangfoo 4096 12月 12 14:49 ../
+-rw-rw-r-- 1 kangfoo kangfoo 1793 12月 12 14:49 pom.xml
+drwxrwxr-x 3 kangfoo kangfoo 4096 12月 12 14:49 test3-api/
+drwxrwxr-x 3 kangfoo kangfoo 4096 12月 12 14:49 test3-consumer/
+drwxrwxr-x 3 kangfoo kangfoo 4096 12月 12 14:49 test3-provider/
+
+
+
diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 000000000000..b610f8b1764a
--- /dev/null
+++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,80 @@
+
+
+  
+    
+      
+        
+          src/main/java
+          
+            **/*.java
+          
+        
+      
+    
+    
+      
+        
+          src/main/java
+          
+            **/*.java
+          
+        
+        
+          src/main/webapp
+          
+            **/*.xml
+          
+        
+        
+          src/main/resources
+          
+            **/*.xml
+          
+        
+        
+          src/test/java
+          
+            **/*.java
+          
+        
+      
+    
+    
+      
+        
+          src/main/java
+          
+            **/*.java
+          
+        
+        
+          src/main/assembly
+          
+            **/*.xml
+            **/*.properties
+          
+        
+        
+          src/main/resources
+          
+            **/*.xml
+          
+        
+        
+          src/test/java
+          
+            **/*.java
+          
+        
+        
+          src/test/resources
+          
+            **/*.xml
+          
+        
+      
+    
+  
+
diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/pom.xml b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/pom.xml
new file mode 100644
index 000000000000..0e6f85553e49
--- /dev/null
+++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/pom.xml
@@ -0,0 +1,44 @@
+
+
+    4.0.0
+    
+        ${groupId}
+        ${rootArtifactId}
+        ${version}
+    
+    ${artifactId}
+    jar
+    ${project.artifactId}
+    The demo module of dubbo project
+    
+        true
+    
+    
+        
+            com.alibaba
+            dubbo
+        
+        
+            javax.servlet
+            javax.servlet-api
+        
+        
+            javax.validation
+            validation-api
+        
+    
+
diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/SerializationOptimizerImpl.java b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/SerializationOptimizerImpl.java
new file mode 100644
index 000000000000..51c2ea26f9ab
--- /dev/null
+++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/SerializationOptimizerImpl.java
@@ -0,0 +1,40 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ * Copyright 1999-2014 dangdang.com.
+ *
+ * Licensed 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 ${package};
+
+import com.alibaba.dubbo.common.serialize.support.SerializationOptimizer;
+import ${package}.user.User;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * This class must be accessible from both the provider and consumer
+ *
+ * @author lishen
+ */
+public class SerializationOptimizerImpl implements SerializationOptimizer {
+
+    public Collection getSerializableClasses() {
+        List classes = new LinkedList();
+        classes.add(User.class);
+        return classes;
+    }
+}
diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/extension/ClientTraceFilter.java b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/extension/ClientTraceFilter.java
new file mode 100644
index 000000000000..b626753c5d07
--- /dev/null
+++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/extension/ClientTraceFilter.java
@@ -0,0 +1,39 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ * Copyright 1999-2014 dangdang.com.
+ *
+ * Licensed 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 ${package}.extension;
+
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientRequestFilter;
+import javax.ws.rs.client.ClientResponseContext;
+import javax.ws.rs.client.ClientResponseFilter;
+import java.io.IOException;
+
+/**
+ * @author lishen
+ */
+public class ClientTraceFilter implements ClientRequestFilter, ClientResponseFilter {
+
+    public void filter(ClientRequestContext requestContext) throws IOException {
+        System.out.println("Client request filter invoked");
+    }
+
+    public void filter(ClientRequestContext clientRequestContext, ClientResponseContext clientResponseContext) throws IOException {
+        System.out.println("Client response filter invoked");
+    }
+}
diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/extension/CustomExceptionMapper.java b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/extension/CustomExceptionMapper.java
new file mode 100644
index 000000000000..a2ed960e38b4
--- /dev/null
+++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/extension/CustomExceptionMapper.java
@@ -0,0 +1,37 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ * Copyright 1999-2014 dangdang.com.
+ *
+ * Licensed 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 ${package}.extension;
+
+import com.alibaba.dubbo.rpc.RpcContext;
+
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+
+/**
+ * @author lishen
+ */
+public class CustomExceptionMapper implements ExceptionMapper {
+
+    public Response toResponse(NotFoundException e) {
+        System.out.println("Exception mapper successfully got an exception: " + e + ":" + e.getMessage());
+        System.out.println("Client IP is " + RpcContext.getContext().getRemoteAddressString());
+        return Response.status(Response.Status.NOT_FOUND).entity("Oops! the requested resource is not found!").type("text/plain").build();
+    }
+}
diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/extension/DynamicTraceBinding.java b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/extension/DynamicTraceBinding.java
new file mode 100644
index 000000000000..ae97a785da74
--- /dev/null
+++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/extension/DynamicTraceBinding.java
@@ -0,0 +1,33 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ * Copyright 1999-2014 dangdang.com.
+ *
+ * Licensed 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 ${package}.extension;
+
+import javax.ws.rs.container.DynamicFeature;
+import javax.ws.rs.container.ResourceInfo;
+import javax.ws.rs.core.FeatureContext;
+
+/**
+ * @author lishen
+ */
+public class DynamicTraceBinding implements DynamicFeature {
+
+    public void configure(ResourceInfo resourceInfo, FeatureContext context) {
+        context.register(DynamicTraceInterceptor.class);
+    }
+}
diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/extension/DynamicTraceInterceptor.java b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/extension/DynamicTraceInterceptor.java
new file mode 100644
index 000000000000..8418dcd253c1
--- /dev/null
+++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/extension/DynamicTraceInterceptor.java
@@ -0,0 +1,45 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ * Copyright 1999-2014 dangdang.com.
+ *
+ * Licensed 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 ${package}.extension;
+
+import javax.annotation.Priority;
+import javax.ws.rs.Priorities;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+import java.io.IOException;
+
+/**
+ * @author lishen
+ */
+@Priority(Priorities.USER)
+public class DynamicTraceInterceptor implements ReaderInterceptor, WriterInterceptor {
+
+    public Object aroundReadFrom(ReaderInterceptorContext readerInterceptorContext) throws IOException, WebApplicationException {
+        System.out.println("Dynamic reader interceptor invoked");
+        return readerInterceptorContext.proceed();
+    }
+
+    public void aroundWriteTo(WriterInterceptorContext writerInterceptorContext) throws IOException, WebApplicationException {
+        System.out.println("Dynamic writer interceptor invoked");
+        writerInterceptorContext.proceed();
+    }
+}
diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/extension/TraceFilter.java b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/extension/TraceFilter.java
new file mode 100644
index 000000000000..e760d90bc660
--- /dev/null
+++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/extension/TraceFilter.java
@@ -0,0 +1,42 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ * Copyright 1999-2014 dangdang.com.
+ *
+ * Licensed 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 ${package}.extension;
+
+import javax.annotation.Priority;
+import javax.ws.rs.Priorities;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import java.io.IOException;
+
+/**
+ * @author lishen
+ */
+@Priority(Priorities.USER)
+public class TraceFilter implements ContainerRequestFilter, ContainerResponseFilter {
+
+    public void filter(ContainerRequestContext requestContext) throws IOException {
+        System.out.println("Request filter invoked");
+    }
+
+    public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) throws IOException {
+        System.out.println("Response filter invoked");
+    }
+}
diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/extension/TraceInterceptor.java b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/extension/TraceInterceptor.java
new file mode 100644
index 000000000000..2c969205eecb
--- /dev/null
+++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/extension/TraceInterceptor.java
@@ -0,0 +1,45 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ * Copyright 1999-2014 dangdang.com.
+ *
+ * Licensed 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 ${package}.extension;
+
+import javax.annotation.Priority;
+import javax.ws.rs.Priorities;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+import java.io.IOException;
+
+/**
+ * @author lishen
+ */
+@Priority(Priorities.USER)
+public class TraceInterceptor implements ReaderInterceptor, WriterInterceptor {
+
+    public Object aroundReadFrom(ReaderInterceptorContext readerInterceptorContext) throws IOException, WebApplicationException {
+        System.out.println("Reader interceptor invoked");
+        return readerInterceptorContext.proceed();
+    }
+
+    public void aroundWriteTo(WriterInterceptorContext writerInterceptorContext) throws IOException, WebApplicationException {
+        System.out.println("Writer interceptor invoked");
+        writerInterceptorContext.proceed();
+    }
+}
diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/user/User.java b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/user/User.java
new file mode 100644
index 000000000000..556de6f43805
--- /dev/null
+++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/user/User.java
@@ -0,0 +1,80 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ * Copyright 1999-2014 dangdang.com.
+ *
+ * Licensed 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 ${package}.user;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+
+/**
+ * @author lishen
+ */
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class User implements Serializable {
+
+    @NotNull
+    @Min(1L)
+    private Long id;
+
+    @JsonProperty("username")
+    @XmlElement(name = "username")
+    @NotNull
+    @Size(min = 6, max = 50)
+    private String name;
+
+    public User() {
+    }
+
+    public User(Long id, String name) {
+        this.id = id;
+        this.name = name;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public String toString() {
+        return "User (" +
+                "id=" + id +
+                ", name='" + name + '${symbol_escape}'' +
+                ')';
+    }
+}
diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/user/UserService.java b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/user/UserService.java
new file mode 100644
index 000000000000..240260c533a1
--- /dev/null
+++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/user/UserService.java
@@ -0,0 +1,28 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ * Copyright 1999-2014 dangdang.com.
+ *
+ * Licensed 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 ${package}.user;
+
+/**
+ * @author lishen
+ */
+public interface UserService {
+    User getUser(Long id);
+
+    Long registerUser(User user);
+}
diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/user/facade/RegistrationResult.java b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/user/facade/RegistrationResult.java
new file mode 100644
index 000000000000..bff9e83fd9c7
--- /dev/null
+++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/user/facade/RegistrationResult.java
@@ -0,0 +1,48 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ * Copyright 1999-2014 dangdang.com.
+ *
+ * Licensed 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 ${package}.user.facade;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+
+/**
+ * DTO to customize the returned message
+ *
+ * @author lishen
+ */
+@XmlRootElement
+public class RegistrationResult implements Serializable {
+
+    private Long id;
+
+    public RegistrationResult() {
+    }
+
+    public RegistrationResult(Long id) {
+        this.id = id;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+}
diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/user/facade/UserRestService.java b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/user/facade/UserRestService.java
new file mode 100644
index 000000000000..9118713a3a40
--- /dev/null
+++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/java/user/facade/UserRestService.java
@@ -0,0 +1,51 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ * Copyright 1999-2014 dangdang.com.
+ *
+ * Licensed 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 ${package}.user.facade;
+
+import ${package}.user.User;
+import com.alibaba.dubbo.rpc.protocol.rest.support.ContentType;
+
+import javax.validation.constraints.Min;
+import javax.ws.rs.*;
+import javax.ws.rs.core.MediaType;
+
+/**
+ * This interface acts as some kind of service broker for the original UserService
+ * 

+ * Here we want to simulate the twitter/weibo rest api, e.g. + *

+ * http://localhost:8888/user/1.json + * http://localhost:8888/user/1.xml + * + * @author lishen + */ + +@Path("users") +@Consumes({MediaType.APPLICATION_JSON, MediaType.TEXT_XML}) +@Produces({ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8}) +public interface UserRestService { + + @GET + @Path("{id : ${symbol_escape}${symbol_escape}d+}") + public User getUser(@Min(value = 1L, message = "User ID must be greater than 1") @PathParam("id") Long id/*, @Context HttpServletRequest request*/); + + @POST + @Path("register") + RegistrationResult registerUser(User user); +} diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/pom.xml b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/pom.xml new file mode 100644 index 000000000000..8a771dd82f28 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/pom.xml @@ -0,0 +1,179 @@ + + + 4.0.0 + + ${groupId} + ${rootArtifactId} + ${version} + + ${artifactId} + jar + ${project.artifactId} + The demo consumer module of dubbo project + + false + + + + ${groupId} + ${rootArtifactId}-api + ${version} + + + com.alibaba + dubbo + + + org.javassist + javassist + + + io.netty + netty + + + org.apache.mina + mina-core + + + org.glassfish.grizzly + grizzly-core + + + org.apache.httpcomponents + httpclient + + + com.alibaba + fastjson + + + com.thoughtworks.xstream + xstream + + + org.apache.bsf + bsf-api + + + org.apache.zookeeper + zookeeper + + + com.github.sgroschupf + zkclient + + + org.apache.curator + curator-framework + + + com.googlecode.xmemcached + xmemcached + + + org.apache.cxf + cxf-rt-frontend-simple + + + org.apache.cxf + cxf-rt-transports-http + + + org.apache.thrift + libthrift + + + com.caucho + hessian + + + javax.servlet + javax.servlet-api + + + org.mortbay.jetty + jetty + + + log4j + log4j + + + org.slf4j + slf4j-api + + + redis.clients + jedis + + + javax.validation + validation-api + + + org.hibernate + hibernate-validator + + + javax.cache + cache-api + + + + + + maven-dependency-plugin + + + unpack + package + + unpack + + + + + com.alibaba + dubbo + ${project.parent.version} + ${project.build.directory}/dubbo + META-INF/assembly/** + + + + + + + + maven-assembly-plugin + + src/main/assembly/assembly.xml + + + + make-assembly + package + + single + + + + + + + diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/main/assembly/assembly.xml b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/main/assembly/assembly.xml new file mode 100644 index 000000000000..3516e43dc66f --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/main/assembly/assembly.xml @@ -0,0 +1,42 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( $symbol_escape = '\' ) + + + assembly + + tar.gz + + true + + + ${symbol_dollar}{project.build.directory}/dubbo/META-INF/assembly/bin + bin + 0755 + + + src/main/assembly/conf + conf + 0644 + + + + + lib + + + diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/main/assembly/conf/dubbo.properties b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/main/assembly/conf/dubbo.properties new file mode 100644 index 000000000000..f6e6daa4122f --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/main/assembly/conf/dubbo.properties @@ -0,0 +1,28 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( $symbol_escape = '\' ) +${symbol_pound}${symbol_pound} +${symbol_pound} Copyright 1999-2011 Alibaba Group. +${symbol_pound} +${symbol_pound} Licensed under the Apache License, Version 2.0 (the "License"); +${symbol_pound} you may not use this file except in compliance with the License. +${symbol_pound} You may obtain a copy of the License at +${symbol_pound} +${symbol_pound} http://www.apache.org/licenses/LICENSE-2.0 +${symbol_pound} +${symbol_pound} Unless required by applicable law or agreed to in writing, software +${symbol_pound} distributed under the License is distributed on an "AS IS" BASIS, +${symbol_pound} WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +${symbol_pound} See the License for the specific language governing permissions and +${symbol_pound} limitations under the License. +${symbol_pound}${symbol_pound} +dubbo.container=log4j,spring +dubbo.application.name=demo-lite-consumer +dubbo.application.owner= +${symbol_pound}dubbo.registry.address=multicast://224.5.6.7:1234 +dubbo.registry.address=zookeeper://127.0.0.1:2181 +${symbol_pound}dubbo.registry.address=redis://127.0.0.1:6379 +${symbol_pound}dubbo.registry.address=dubbo://127.0.0.1:9090 +dubbo.monitor.protocol=registry +dubbo.log4j.file=logs/dubbo-demo-consumer.log +dubbo.log4j.level=WARN diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/main/java/consumer/DemoAction.java b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/main/java/consumer/DemoAction.java new file mode 100644 index 000000000000..3ebc5e7f8cdd --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/main/java/consumer/DemoAction.java @@ -0,0 +1,52 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( $symbol_escape = '\' ) +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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 ${package}.consumer; + +import ${package}.user.User; +import ${package}.user.UserService; +import ${package}.user.facade.UserRestService; + +/** + * User: kangfoo + * Date: 14-12-9 + * Time: 下午4:12 + */ +public class DemoAction { + + private UserRestService userRestService; + private UserService userService; + + public void setUserService(UserService userService) { + this.userService = userService; + } + + public void setUserRestService(UserRestService userRestService) { + this.userRestService = userRestService; + } + + public void start() throws Exception { + + + User user = new User(1L, "larrypage"); + System.out.println("SUCESS: registered user with id " + userRestService.registerUser(user).getId()); + + System.out.println("SUCESS: got user " + userService.getUser(1L)); + } + +} diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/main/resources/META-INF/spring/dubbo-demo-lite-action.xml b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/main/resources/META-INF/spring/dubbo-demo-lite-action.xml new file mode 100644 index 000000000000..ce672ebbeee7 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/main/resources/META-INF/spring/dubbo-demo-lite-action.xml @@ -0,0 +1,30 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( $symbol_escape = '\' ) + + + + + + + + + + + diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/main/resources/META-INF/spring/dubbo-demo-lite-consumer.xml b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/main/resources/META-INF/spring/dubbo-demo-lite-consumer.xml new file mode 100644 index 000000000000..63a302ba7e9f --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/main/resources/META-INF/spring/dubbo-demo-lite-consumer.xml @@ -0,0 +1,24 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( $symbol_escape = '\' ) + + + + + + + + + + + + + + + + + diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/test/java/consumer/DemoConsumer.java b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/test/java/consumer/DemoConsumer.java new file mode 100644 index 000000000000..01ca2d6aa467 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/test/java/consumer/DemoConsumer.java @@ -0,0 +1,27 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( $symbol_escape = '\' ) +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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 ${package}.consumer; + +public class DemoConsumer { + + public static void main(String[] args) { + com.alibaba.dubbo.container.Main.main(args); + } + +} diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/test/java/consumer/RestClient.java b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/test/java/consumer/RestClient.java new file mode 100644 index 000000000000..8512b0234656 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/test/java/consumer/RestClient.java @@ -0,0 +1,92 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( $symbol_escape = '\' ) +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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 ${package}.consumer; + +import ${package}.user.User; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +/** + * @author lishen + */ +public class RestClient { + + public static void main(String[] args) { + final String port = "8888"; +// final String port = "8080"; + +// for (int i = 0; i < 500; i++) { +// final int index = i + 1; +// new Thread(new Runnable() { +// public void run() { +// System.out.println("Starting thread " + index + "..."); +// for (int j = 0; j < 500; j++) { + registerUser("http://localhost:" + port + "/services/users/register.json", MediaType.APPLICATION_JSON_TYPE); + + registerUser("http://localhost:" + port + "/services/users/register.xml", MediaType.TEXT_XML_TYPE); + + getUser("http://localhost:" + port + "/services/users/1.json"); + + getUser("http://localhost:" + port + "/services/users/2.xml"); + +// } +// } +// }).start(); +// } + } + + private static void registerUser(String url, MediaType mediaType) { + System.out.println("Registering user via " + url); + User user = new User(1L, "larrypage"); + Client client = ClientBuilder.newClient(); + WebTarget target = client.target(url); + Response response = target.request().post(Entity.entity(user, mediaType)); + + try { + if (response.getStatus() != 200) { + throw new RuntimeException("Failed with HTTP error code : " + response.getStatus()); + } + System.out.println("Successfully got result: " + response.readEntity(String.class)); + } finally { + response.close(); + client.close(); + } + } + + private static void getUser(String url) { + System.out.println("Getting user via " + url); + Client client = ClientBuilder.newClient(); + WebTarget target = client.target(url); + Response response = target.request().get(); + try { + if (response.getStatus() != 200) { + throw new RuntimeException("Failed with HTTP error code : " + response.getStatus()); + } + System.out.println("Successfully got result: " + response.readEntity(String.class)); + } finally { + response.close(); + client.close(); + } + } +} diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/test/resources/log4j.xml b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/test/resources/log4j.xml new file mode 100644 index 000000000000..77898f221fdb --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-consumer/src/test/resources/log4j.xml @@ -0,0 +1,31 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( $symbol_escape = '\' ) + + + + + + + + + + + + + + diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-provider/pom.xml b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-provider/pom.xml new file mode 100644 index 000000000000..3c40d8258686 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-provider/pom.xml @@ -0,0 +1,193 @@ + + + 4.0.0 + + ${groupId} + ${rootArtifactId} + ${version} + + ${artifactId} + war + ${project.artifactId} + The demo provider module of dubbo project + + false + + + + ${groupId} + ${rootArtifactId}-api + ${version} + + + com.alibaba + dubbo + + + org.javassist + javassist + + + io.netty + netty + + + org.apache.mina + mina-core + + + org.glassfish.grizzly + grizzly-core + + + org.apache.httpcomponents + httpclient + + + com.alibaba + fastjson + + + com.thoughtworks.xstream + xstream + + + org.apache.bsf + bsf-api + + + org.apache.zookeeper + zookeeper + + + com.github.sgroschupf + zkclient + + + org.apache.curator + curator-framework + + + com.googlecode.xmemcached + xmemcached + + + org.apache.cxf + cxf-rt-frontend-simple + + + org.apache.cxf + cxf-rt-transports-http + + + org.apache.thrift + libthrift + + + com.caucho + hessian + + + javax.servlet + javax.servlet-api + + + org.mortbay.jetty + jetty + + + org.mortbay.jetty + servlet-api + + + + + log4j + log4j + + + org.slf4j + slf4j-api + + + redis.clients + jedis + + + javax.validation + validation-api + + + org.hibernate + hibernate-validator + + + javax.cache + cache-api + + + javax.ws.rs + javax.ws.rs-api + 2.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-provider/src/main/java/user/UserServiceImpl.java b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-provider/src/main/java/user/UserServiceImpl.java new file mode 100644 index 000000000000..b084730140a6 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-provider/src/main/java/user/UserServiceImpl.java @@ -0,0 +1,41 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( $symbol_escape = '\' ) +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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 ${package}.user; + +import java.util.concurrent.atomic.AtomicLong; + +/** + * User: kangfoo + * Date: 14-12-9 + * Time: 下午3:45 + */ +public class UserServiceImpl implements UserService { + + private final AtomicLong idGen = new AtomicLong(); + + public User getUser(Long id) { + return new User(id, "username" + id); + } + + + public Long registerUser(User user) { +// System.out.println("Username is " + user.getName()); + return idGen.incrementAndGet(); + } +} diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-provider/src/main/java/user/facade/UserRestServiceImpl.java b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-provider/src/main/java/user/facade/UserRestServiceImpl.java new file mode 100644 index 000000000000..3bf9cf567cbb --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-provider/src/main/java/user/facade/UserRestServiceImpl.java @@ -0,0 +1,66 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( $symbol_escape = '\' ) +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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 ${package}.user.facade; + +import ${package}.user.User; +import ${package}.user.UserService; +import com.alibaba.dubbo.rpc.RpcContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.Min; +import javax.ws.rs.PathParam; + +/** + * User: kangfoo + * Date: 14-12-9 + * Time: 下午3:45 + */ +public class UserRestServiceImpl implements UserRestService { + + private static final Logger logger = LoggerFactory.getLogger(UserRestServiceImpl.class); + + private UserService userService; + + public void setUserService(UserService userService) { + this.userService = userService; + } + + @Override + public User getUser(@Min(value = 1L, message = "User ID must be greater than 1") @PathParam("id") Long id) { + // test context injection +// System.out.println("Client address from @Context injection: " + (request != null ? request.getRemoteAddr() : "")); +// System.out.println("Client address from RpcContext: " + RpcContext.getContext().getRemoteAddressString()); + if (RpcContext.getContext().getRequest(HttpServletRequest.class) != null) { + System.out.println("Client IP address from RpcContext: " + RpcContext.getContext().getRequest(HttpServletRequest.class).getRemoteAddr()); + } + if (RpcContext.getContext().getResponse(HttpServletResponse.class) != null) { + System.out.println("Response object from RpcContext: " + RpcContext.getContext().getResponse(HttpServletResponse.class)); + } + return userService.getUser(id); + } + + @Override + public RegistrationResult registerUser(User user) { + return new RegistrationResult(userService.registerUser(user)); + } + +} diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-provider/src/main/resources/META-INF/spring/dubbo-demo-lite-provider.xml b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-provider/src/main/resources/META-INF/spring/dubbo-demo-lite-provider.xml new file mode 100644 index 000000000000..bee031cc66a0 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-provider/src/main/resources/META-INF/spring/dubbo-demo-lite-provider.xml @@ -0,0 +1,80 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( $symbol_escape = '\' ) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-provider/src/main/resources/log4j.xml b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-provider/src/main/resources/log4j.xml new file mode 100644 index 000000000000..77898f221fdb --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-provider/src/main/resources/log4j.xml @@ -0,0 +1,31 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( $symbol_escape = '\' ) + + + + + + + + + + + + + + diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-provider/src/main/webapp/WEB-INF/web.xml b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-provider/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000000..f9cf14fa6769 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-provider/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,33 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( $symbol_escape = '\' ) + + + + + + contextConfigLocation + /WEB-INF/classes/META-INF/spring/dubbo-demo-lite-provider.xml + + + + + com.alibaba.dubbo.remoting.http.servlet.BootstrapListener + + + + org.springframework.web.context.ContextLoaderListener + + + + dispatcher + com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet + 1 + + + + dispatcher + /services/* + + diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-provider/src/test/java/provider/DemoProvider.java b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-provider/src/test/java/provider/DemoProvider.java new file mode 100644 index 000000000000..258856f9e56b --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/__rootArtifactId__-provider/src/test/java/provider/DemoProvider.java @@ -0,0 +1,37 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( $symbol_escape = '\' ) +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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 ${package}.provider; + +public class DemoProvider { + + public static void main(String[] args) { +// new Thread(new Runnable() { +// public void run() { +// try { +// Thread.sleep(20000); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// ProtocolConfig.destroyAll(); +// } +// }).start(); + com.alibaba.dubbo.container.Main.main(args); + } + +} diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/pom.xml b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/pom.xml new file mode 100644 index 000000000000..561a683e509e --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite-archetype/src/main/resources/archetype-resources/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + com.alibaba + dubbo-parent + 2.8.4 + + ${artifactId} + ${groupId} + pom + ${project.artifactId} + The demo lite module of dubbo project + ${version} + + true + + + + + + com.alibaba + dubbo + 2.8.4 + + + + diff --git a/dubbo-tool/dubbo-demo-lite-archetype/src/test/resources/projects/basic/archetype.properties b/dubbo-tool/dubbo-demo-lite-archetype/src/test/resources/projects/basic/archetype.properties new file mode 100644 index 000000000000..dc09b753b730 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite-archetype/src/test/resources/projects/basic/archetype.properties @@ -0,0 +1,5 @@ +#Thu Dec 11 15:57:06 CST 2014 +package=it.pkg +version=0.1-SNAPSHOT +groupId=archetype.it +artifactId=basic diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/pom.xml b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/pom.xml new file mode 100644 index 000000000000..fb06b6404790 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + + com.alibaba + dubbo-demo-lite + 2.8.4 + + dubbo-demo-lite-api + jar + ${project.artifactId} + The demo module of dubbo project + + true + + + + com.alibaba + dubbo + + + javax.servlet + javax.servlet-api + + + javax.validation + validation-api + + + diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/SerializationOptimizerImpl.java b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/SerializationOptimizerImpl.java new file mode 100644 index 000000000000..f82006a14c60 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/SerializationOptimizerImpl.java @@ -0,0 +1,37 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demolite; + +import com.alibaba.dubbo.common.serialize.support.SerializationOptimizer; +import com.alibaba.dubbo.demolite.user.User; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +/** + * This class must be accessible from both the provider and consumer + * + * @author lishen + */ +public class SerializationOptimizerImpl implements SerializationOptimizer { + + public Collection getSerializableClasses() { + List classes = new LinkedList(); + classes.add(User.class); + return classes; + } +} diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/extension/ClientTraceFilter.java b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/extension/ClientTraceFilter.java new file mode 100644 index 000000000000..108b09fbc2b7 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/extension/ClientTraceFilter.java @@ -0,0 +1,36 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demolite.extension; + +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientRequestFilter; +import javax.ws.rs.client.ClientResponseContext; +import javax.ws.rs.client.ClientResponseFilter; +import java.io.IOException; + +/** + * @author lishen + */ +public class ClientTraceFilter implements ClientRequestFilter, ClientResponseFilter { + + public void filter(ClientRequestContext requestContext) throws IOException { + System.out.println("Client request filter invoked"); + } + + public void filter(ClientRequestContext clientRequestContext, ClientResponseContext clientResponseContext) throws IOException { + System.out.println("Client response filter invoked"); + } +} diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/extension/CustomExceptionMapper.java b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/extension/CustomExceptionMapper.java new file mode 100644 index 000000000000..d73838a18ece --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/extension/CustomExceptionMapper.java @@ -0,0 +1,34 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demolite.extension; + +import com.alibaba.dubbo.rpc.RpcContext; + +import javax.ws.rs.NotFoundException; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; + +/** + * @author lishen + */ +public class CustomExceptionMapper implements ExceptionMapper { + + public Response toResponse(NotFoundException e) { + System.out.println("Exception mapper successfully got an exception: " + e + ":" + e.getMessage()); + System.out.println("Client IP is " + RpcContext.getContext().getRemoteAddressString()); + return Response.status(Response.Status.NOT_FOUND).entity("Oops! the requested resource is not found!").type("text/plain").build(); + } +} diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/extension/DynamicTraceBinding.java b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/extension/DynamicTraceBinding.java new file mode 100644 index 000000000000..eaf81d4d5570 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/extension/DynamicTraceBinding.java @@ -0,0 +1,30 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demolite.extension; + +import javax.ws.rs.container.DynamicFeature; +import javax.ws.rs.container.ResourceInfo; +import javax.ws.rs.core.FeatureContext; + +/** + * @author lishen + */ +public class DynamicTraceBinding implements DynamicFeature { + + public void configure(ResourceInfo resourceInfo, FeatureContext context) { + context.register(DynamicTraceInterceptor.class); + } +} diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/extension/DynamicTraceInterceptor.java b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/extension/DynamicTraceInterceptor.java new file mode 100644 index 000000000000..8f6a249e1fad --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/extension/DynamicTraceInterceptor.java @@ -0,0 +1,42 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demolite.extension; + +import javax.annotation.Priority; +import javax.ws.rs.Priorities; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.ext.ReaderInterceptor; +import javax.ws.rs.ext.ReaderInterceptorContext; +import javax.ws.rs.ext.WriterInterceptor; +import javax.ws.rs.ext.WriterInterceptorContext; +import java.io.IOException; + +/** + * @author lishen + */ +@Priority(Priorities.USER) +public class DynamicTraceInterceptor implements ReaderInterceptor, WriterInterceptor { + + public Object aroundReadFrom(ReaderInterceptorContext readerInterceptorContext) throws IOException, WebApplicationException { + System.out.println("Dynamic reader interceptor invoked"); + return readerInterceptorContext.proceed(); + } + + public void aroundWriteTo(WriterInterceptorContext writerInterceptorContext) throws IOException, WebApplicationException { + System.out.println("Dynamic writer interceptor invoked"); + writerInterceptorContext.proceed(); + } +} diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/extension/TraceFilter.java b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/extension/TraceFilter.java new file mode 100644 index 000000000000..457a28fde86b --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/extension/TraceFilter.java @@ -0,0 +1,39 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demolite.extension; + +import javax.annotation.Priority; +import javax.ws.rs.Priorities; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import java.io.IOException; + +/** + * @author lishen + */ +@Priority(Priorities.USER) +public class TraceFilter implements ContainerRequestFilter, ContainerResponseFilter { + + public void filter(ContainerRequestContext requestContext) throws IOException { + System.out.println("Request filter invoked"); + } + + public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) throws IOException { + System.out.println("Response filter invoked"); + } +} diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/extension/TraceInterceptor.java b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/extension/TraceInterceptor.java new file mode 100644 index 000000000000..4354f90850f5 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/extension/TraceInterceptor.java @@ -0,0 +1,42 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demolite.extension; + +import javax.annotation.Priority; +import javax.ws.rs.Priorities; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.ext.ReaderInterceptor; +import javax.ws.rs.ext.ReaderInterceptorContext; +import javax.ws.rs.ext.WriterInterceptor; +import javax.ws.rs.ext.WriterInterceptorContext; +import java.io.IOException; + +/** + * @author lishen + */ +@Priority(Priorities.USER) +public class TraceInterceptor implements ReaderInterceptor, WriterInterceptor { + + public Object aroundReadFrom(ReaderInterceptorContext readerInterceptorContext) throws IOException, WebApplicationException { + System.out.println("Reader interceptor invoked"); + return readerInterceptorContext.proceed(); + } + + public void aroundWriteTo(WriterInterceptorContext writerInterceptorContext) throws IOException, WebApplicationException { + System.out.println("Writer interceptor invoked"); + writerInterceptorContext.proceed(); + } +} diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/user/User.java b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/user/User.java new file mode 100644 index 000000000000..005ff3794a52 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/user/User.java @@ -0,0 +1,77 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demolite.user; + +import org.codehaus.jackson.annotate.JsonProperty; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; + +/** + * @author lishen + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class User implements Serializable { + + @NotNull + @Min(1L) + private Long id; + + @JsonProperty("username") + @XmlElement(name = "username") + @NotNull + @Size(min = 6, max = 50) + private String name; + + public User() { + } + + public User(Long id, String name) { + this.id = id; + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return "User (" + + "id=" + id + + ", name='" + name + '\'' + + ')'; + } +} diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/user/UserService.java b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/user/UserService.java new file mode 100644 index 000000000000..43b503067564 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/user/UserService.java @@ -0,0 +1,25 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demolite.user; + +/** + * @author lishen + */ +public interface UserService { + User getUser(Long id); + + Long registerUser(User user); +} diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/user/facade/RegistrationResult.java b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/user/facade/RegistrationResult.java new file mode 100644 index 000000000000..c58f7d73d19b --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/user/facade/RegistrationResult.java @@ -0,0 +1,45 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demolite.user.facade; + +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; + +/** + * DTO to customize the returned message + * + * @author lishen + */ +@XmlRootElement +public class RegistrationResult implements Serializable { + + private Long id; + + public RegistrationResult() { + } + + public RegistrationResult(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } +} diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/user/facade/UserRestService.java b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/user/facade/UserRestService.java new file mode 100644 index 000000000000..b753eea68bdb --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-api/src/main/java/com/alibaba/dubbo/demolite/user/facade/UserRestService.java @@ -0,0 +1,48 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demolite.user.facade; + +import com.alibaba.dubbo.demolite.user.User; +import com.alibaba.dubbo.rpc.protocol.rest.support.ContentType; + +import javax.validation.constraints.Min; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; + +/** + * This interface acts as some kind of service broker for the original UserService + + * Here we want to simulate the twitter/weibo rest api, e.g. + * + * http://localhost:8888/user/1.json + * http://localhost:8888/user/1.xml + * + * @author lishen + */ + +@Path("users") +@Consumes({MediaType.APPLICATION_JSON, MediaType.TEXT_XML}) +@Produces({ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8}) +public interface UserRestService { + + @GET + @Path("{id : \\d+}") + public User getUser(@Min(value=1L, message="User ID must be greater than 1") @PathParam("id") Long id/*, @Context HttpServletRequest request*/) ; + + @POST + @Path("register") + RegistrationResult registerUser(User user); +} diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/pom.xml b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/pom.xml new file mode 100644 index 000000000000..e59c2df0903c --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/pom.xml @@ -0,0 +1,180 @@ + + + 4.0.0 + + com.alibaba + dubbo-demo-lite + 2.8.4 + + dubbo-demo-lite-consumer + jar + ${project.artifactId} + The demo consumer module of dubbo project + + false + + + + com.alibaba + dubbo-demo-lite-api + ${project.parent.version} + + + com.alibaba + dubbo + + + org.javassist + javassist + + + io.netty + netty + + + org.apache.mina + mina-core + + + org.glassfish.grizzly + grizzly-core + + + org.apache.httpcomponents + httpclient + + + com.alibaba + fastjson + + + com.thoughtworks.xstream + xstream + + + org.apache.bsf + bsf-api + + + org.apache.zookeeper + zookeeper + + + com.github.sgroschupf + zkclient + + + org.apache.curator + curator-framework + + + com.googlecode.xmemcached + xmemcached + + + org.apache.cxf + cxf-rt-frontend-simple + + + org.apache.cxf + cxf-rt-transports-http + + + org.apache.thrift + libthrift + + + com.caucho + hessian + + + javax.servlet + javax.servlet-api + + + org.mortbay.jetty + jetty + + + log4j + log4j + + + org.slf4j + slf4j-api + + + redis.clients + jedis + + + javax.validation + validation-api + + + org.hibernate + hibernate-validator + + + javax.cache + cache-api + + + + + + maven-dependency-plugin + + + unpack + package + + unpack + + + + + com.alibaba + dubbo + ${project.parent.version} + ${project.build.directory}/dubbo + META-INF/assembly/** + + + + + + + + maven-assembly-plugin + + src/main/assembly/assembly.xml + + + + make-assembly + package + + single + + + + + + + diff --git a/dubbo-demo/dubbo-demo-provider/src/main/assembly/assembly.xml b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/main/assembly/assembly.xml similarity index 96% rename from dubbo-demo/dubbo-demo-provider/src/main/assembly/assembly.xml rename to dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/main/assembly/assembly.xml index 25235d9064e2..1bdbe518dcd3 100644 --- a/dubbo-demo/dubbo-demo-provider/src/main/assembly/assembly.xml +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/main/assembly/assembly.xml @@ -1,39 +1,39 @@ - - - assembly - - tar.gz - - true - - - ${project.build.directory}/dubbo/META-INF/assembly/bin - bin - 0755 - - - src/main/assembly/conf - conf - 0644 - - - - - lib - - - \ No newline at end of file + + + assembly + + tar.gz + + true + + + ${project.build.directory}/dubbo/META-INF/assembly/bin + bin + 0755 + + + src/main/assembly/conf + conf + 0644 + + + + + lib + + + diff --git a/dubbo-demo/dubbo-demo-consumer/src/test/resources/dubbo.properties b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/main/assembly/conf/dubbo.properties similarity index 73% rename from dubbo-demo/dubbo-demo-consumer/src/test/resources/dubbo.properties rename to dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/main/assembly/conf/dubbo.properties index 32723f9c1b30..8d1835e8f0b5 100644 --- a/dubbo-demo/dubbo-demo-consumer/src/test/resources/dubbo.properties +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/main/assembly/conf/dubbo.properties @@ -1,25 +1,25 @@ -## -# Copyright 1999-2011 Alibaba Group. -# -# Licensed 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. -## -dubbo.container=log4j,spring -dubbo.application.name=demo-consumer -dubbo.application.owner= -dubbo.registry.address=multicast://224.5.6.7:1234 -#dubbo.registry.address=zookeeper://127.0.0.1:2181 -#dubbo.registry.address=redis://127.0.0.1:6379 -#dubbo.registry.address=dubbo://127.0.0.1:9090 -#dubbo.monitor.protocol=registry -#dubbo.log4j.file=logs/dubbo-demo-consumer.log -#dubbo.log4j.level=WARN \ No newline at end of file +## +# Copyright 1999-2011 Alibaba Group. +# +# Licensed 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. +## +dubbo.container=log4j,spring +dubbo.application.name=demo-lite-consumer +dubbo.application.owner= +#dubbo.registry.address=multicast://224.5.6.7:1234 +dubbo.registry.address=zookeeper://127.0.0.1:2181 +#dubbo.registry.address=redis://127.0.0.1:6379 +#dubbo.registry.address=dubbo://127.0.0.1:9090 +dubbo.monitor.protocol=registry +dubbo.log4j.file=logs/dubbo-demo-consumer.log +dubbo.log4j.level=WARN diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/main/java/com/alibaba/dubbo/demolite/consumer/DemoAction.java b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/main/java/com/alibaba/dubbo/demolite/consumer/DemoAction.java new file mode 100644 index 000000000000..32699c7b51a2 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/main/java/com/alibaba/dubbo/demolite/consumer/DemoAction.java @@ -0,0 +1,50 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.demolite.consumer; + +import com.alibaba.dubbo.demolite.user.User; +import com.alibaba.dubbo.demolite.user.UserService; +import com.alibaba.dubbo.demolite.user.facade.UserRestService; + +/** + * + * User: kangfoo + * Date: 14-12-9 + * Time: 下午4:12 + */ +public class DemoAction { + + private UserRestService userRestService; + private UserService userService; + + public void setUserService(UserService userService) { + this.userService = userService; + } + + public void setUserRestService(UserRestService userRestService) { + this.userRestService = userRestService; + } + + public void start() throws Exception { + + + User user = new User(1L, "larrypage"); + System.out.println("SUCESS: registered user with id " + userRestService.registerUser(user).getId()); + + System.out.println("SUCESS: got user " + userService.getUser(1L)); + } + +} diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/main/resources/META-INF/spring/dubbo-demo-lite-action.xml b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/main/resources/META-INF/spring/dubbo-demo-lite-action.xml new file mode 100644 index 000000000000..c0aa4f9b6e89 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/main/resources/META-INF/spring/dubbo-demo-lite-action.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/main/resources/META-INF/spring/dubbo-demo-lite-consumer.xml b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/main/resources/META-INF/spring/dubbo-demo-lite-consumer.xml new file mode 100644 index 000000000000..88f5164cbde2 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/main/resources/META-INF/spring/dubbo-demo-lite-consumer.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/test/java/com/alibaba/dubbo/demolite/consumer/DemoConsumer.java b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/test/java/com/alibaba/dubbo/demolite/consumer/DemoConsumer.java new file mode 100644 index 000000000000..e87a3f3acc6e --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/test/java/com/alibaba/dubbo/demolite/consumer/DemoConsumer.java @@ -0,0 +1,24 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.demolite.consumer; + +public class DemoConsumer { + + public static void main(String[] args) { + com.alibaba.dubbo.container.Main.main(args); + } + +} diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/test/java/com/alibaba/dubbo/demolite/consumer/RestClient.java b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/test/java/com/alibaba/dubbo/demolite/consumer/RestClient.java new file mode 100644 index 000000000000..5e4942160b77 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/test/java/com/alibaba/dubbo/demolite/consumer/RestClient.java @@ -0,0 +1,89 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demolite.consumer; + +import com.alibaba.dubbo.demolite.user.User; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +/** + * @author lishen + */ +public class RestClient { + + public static void main(String[] args) { + final String port = "8888"; +// final String port = "8080"; + +// for (int i = 0; i < 500; i++) { +// final int index = i + 1; +// new Thread(new Runnable() { +// public void run() { +// System.out.println("Starting thread " + index + "..."); +// for (int j = 0; j < 500; j++) { + registerUser("http://localhost:" + port + "/services/users/register.json", MediaType.APPLICATION_JSON_TYPE); + + registerUser("http://localhost:" + port + "/services/users/register.xml", MediaType.TEXT_XML_TYPE); + + getUser("http://localhost:" + port + "/services/users/1.json"); + + getUser("http://localhost:" + port + "/services/users/2.xml"); + +// } +// } +// }).start(); +// } + } + + private static void registerUser(String url, MediaType mediaType) { + System.out.println("Registering user via " + url); + User user = new User(1L, "larrypage"); + Client client = ClientBuilder.newClient(); + WebTarget target = client.target(url); + Response response = target.request().post(Entity.entity(user, mediaType)); + + try { + if (response.getStatus() != 200) { + throw new RuntimeException("Failed with HTTP error code : " + response.getStatus()); + } + System.out.println("Successfully got result: " + response.readEntity(String.class)); + } finally { + response.close(); + client.close(); + } + } + + private static void getUser(String url) { + System.out.println("Getting user via " + url); + Client client = ClientBuilder.newClient(); + WebTarget target = client.target(url); + Response response = target.request().get(); + try { + if (response.getStatus() != 200) { + throw new RuntimeException("Failed with HTTP error code : " + response.getStatus()); + } + System.out.println("Successfully got result: " + response.readEntity(String.class)); + } finally { + response.close(); + client.close(); + } + } +} diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/test/resources/log4j.xml b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/test/resources/log4j.xml new file mode 100644 index 000000000000..5375cc32f395 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-consumer/src/test/resources/log4j.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-provider/pom.xml b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-provider/pom.xml new file mode 100644 index 000000000000..ab2cead41cd3 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-provider/pom.xml @@ -0,0 +1,195 @@ + + + 4.0.0 + + com.alibaba + dubbo-demo-lite + 2.8.4 + + dubbo-demo-lite-provider + war + ${project.artifactId} + The demo provider module of dubbo project + + false + + + + com.alibaba + dubbo-demo-lite-api + ${project.parent.version} + + + com.alibaba + dubbo + ${project.parent.version} + + + org.javassist + javassist + + + io.netty + netty + + + org.apache.mina + mina-core + + + org.glassfish.grizzly + grizzly-core + + + org.apache.httpcomponents + httpclient + + + com.alibaba + fastjson + + + com.thoughtworks.xstream + xstream + + + org.apache.bsf + bsf-api + + + org.apache.zookeeper + zookeeper + + + com.github.sgroschupf + zkclient + + + org.apache.curator + curator-framework + + + com.googlecode.xmemcached + xmemcached + + + org.apache.cxf + cxf-rt-frontend-simple + + + org.apache.cxf + cxf-rt-transports-http + + + org.apache.thrift + libthrift + + + com.caucho + hessian + + + javax.servlet + javax.servlet-api + + + org.mortbay.jetty + jetty + + + org.mortbay.jetty + servlet-api + + + + + log4j + log4j + + + org.slf4j + slf4j-api + + + redis.clients + jedis + + + javax.validation + validation-api + + + org.hibernate + hibernate-validator + + + javax.cache + cache-api + + + javax.ws.rs + javax.ws.rs-api + 2.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-provider/src/main/java/com/alibaba/dubbo/demolite/user/UserServiceImpl.java b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-provider/src/main/java/com/alibaba/dubbo/demolite/user/UserServiceImpl.java new file mode 100644 index 000000000000..837a0bc8bec5 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-provider/src/main/java/com/alibaba/dubbo/demolite/user/UserServiceImpl.java @@ -0,0 +1,38 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demolite.user; + +import java.util.concurrent.atomic.AtomicLong; + +/** + * User: kangfoo + * Date: 14-12-9 + * Time: 下午3:45 + */ +public class UserServiceImpl implements UserService { + + private final AtomicLong idGen = new AtomicLong(); + + public User getUser(Long id) { + return new User(id, "username" + id); + } + + + public Long registerUser(User user) { +// System.out.println("Username is " + user.getName()); + return idGen.incrementAndGet(); + } +} diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-provider/src/main/java/com/alibaba/dubbo/demolite/user/facade/UserRestServiceImpl.java b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-provider/src/main/java/com/alibaba/dubbo/demolite/user/facade/UserRestServiceImpl.java new file mode 100644 index 000000000000..ccbaa904ce14 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-provider/src/main/java/com/alibaba/dubbo/demolite/user/facade/UserRestServiceImpl.java @@ -0,0 +1,63 @@ +/** + * Copyright 1999-2014 dangdang.com. + * + * Licensed 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.demolite.user.facade; + +import com.alibaba.dubbo.demolite.user.User; +import com.alibaba.dubbo.demolite.user.UserService; +import com.alibaba.dubbo.rpc.RpcContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.Min; +import javax.ws.rs.PathParam; + +/** + * User: kangfoo + * Date: 14-12-9 + * Time: 下午3:45 + */ +public class UserRestServiceImpl implements UserRestService { + + private static final Logger logger = LoggerFactory.getLogger(UserRestServiceImpl.class); + + private UserService userService; + + public void setUserService(UserService userService) { + this.userService = userService; + } + + @Override + public User getUser(@Min(value = 1L, message = "User ID must be greater than 1") @PathParam("id") Long id) { + // test context injection +// System.out.println("Client address from @Context injection: " + (request != null ? request.getRemoteAddr() : "")); +// System.out.println("Client address from RpcContext: " + RpcContext.getContext().getRemoteAddressString()); + if (RpcContext.getContext().getRequest(HttpServletRequest.class) != null) { + System.out.println("Client IP address from RpcContext: " + RpcContext.getContext().getRequest(HttpServletRequest.class).getRemoteAddr()); + } + if (RpcContext.getContext().getResponse(HttpServletResponse.class) != null) { + System.out.println("Response object from RpcContext: " + RpcContext.getContext().getResponse(HttpServletResponse.class)); + } + return userService.getUser(id); + } + + @Override + public RegistrationResult registerUser(User user) { + return new RegistrationResult(userService.registerUser(user)); + } + +} diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-provider/src/main/resources/META-INF/spring/dubbo-demo-lite-provider.xml b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-provider/src/main/resources/META-INF/spring/dubbo-demo-lite-provider.xml new file mode 100644 index 000000000000..3d4f93e308c9 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-provider/src/main/resources/META-INF/spring/dubbo-demo-lite-provider.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-provider/src/main/resources/log4j.xml b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-provider/src/main/resources/log4j.xml new file mode 100644 index 000000000000..33bf5d8a725d --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-provider/src/main/resources/log4j.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-provider/src/main/webapp/WEB-INF/web.xml b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-provider/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000000..242c3741c52f --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-provider/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,30 @@ + + + + + + contextConfigLocation + /WEB-INF/classes/META-INF/spring/dubbo-demo-lite-provider.xml + + + + + com.alibaba.dubbo.remoting.http.servlet.BootstrapListener + + + + org.springframework.web.context.ContextLoaderListener + + + + dispatcher + com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet + 1 + + + + dispatcher + /services/* + + diff --git a/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-provider/src/test/java/com/alibaba/dubbo/demolite/provider/DemoProvider.java b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-provider/src/test/java/com/alibaba/dubbo/demolite/provider/DemoProvider.java new file mode 100644 index 000000000000..eaa78d67af21 --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/dubbo-demo-lite-provider/src/test/java/com/alibaba/dubbo/demolite/provider/DemoProvider.java @@ -0,0 +1,34 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed 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.demolite.provider; + +public class DemoProvider { + + public static void main(String[] args) { +// new Thread(new Runnable() { +// public void run() { +// try { +// Thread.sleep(20000); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// ProtocolConfig.destroyAll(); +// } +// }).start(); + com.alibaba.dubbo.container.Main.main(args); + } + +} diff --git a/dubbo-tool/dubbo-demo-lite/pom.xml b/dubbo-tool/dubbo-demo-lite/pom.xml new file mode 100644 index 000000000000..b43142ae691e --- /dev/null +++ b/dubbo-tool/dubbo-demo-lite/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + com.alibaba + dubbo-parent + 2.8.4 + + dubbo-demo-lite + pom + ${project.artifactId} + The demo lite module of dubbo project + + true + + + dubbo-demo-lite-api + dubbo-demo-lite-provider + dubbo-demo-lite-consumer + + + + + + com.alibaba + dubbo + 2.8.4 + + + + diff --git a/dubbo/pom.xml b/dubbo/pom.xml index c93af6e3bec8..1ff4074b8846 100644 --- a/dubbo/pom.xml +++ b/dubbo/pom.xml @@ -1,472 +1,545 @@ - - - 4.0.0 - - com.alibaba - dubbo-parent - 2.4.3 - - dubbo - jar - ${project.artifactId} - The all in one project of dubbo - - false - - - - com.alibaba - dubbo-config-api - ${project.parent.version} - - - org.mortbay.jetty - jetty - - - - - com.alibaba - dubbo-config-spring - ${project.parent.version} - - - com.alibaba - dubbo-remoting-netty - ${project.parent.version} - - - com.alibaba - dubbo-remoting-mina - ${project.parent.version} - - - org.apache.mina - mina-core - - - org.slf4j - slf4j-api - - - - - com.alibaba - dubbo-remoting-grizzly - ${project.parent.version} - - - org.glassfish.grizzly - grizzly-core - - - - - com.alibaba - dubbo-remoting-p2p - ${project.parent.version} - - - com.alibaba - dubbo-remoting-http - ${project.parent.version} - - - org.mortbay.jetty - jetty - - - org.apache.httpcomponents - httpclient - - - - - com.alibaba - dubbo-rpc-default - ${project.parent.version} - - - com.alibaba - dubbo-rpc-injvm - ${project.parent.version} - - - com.alibaba - dubbo-rpc-rmi - ${project.parent.version} - - - com.alibaba - dubbo-rpc-hessian - ${project.parent.version} - - - com.caucho - hessian - - - - - com.alibaba - dubbo-rpc-http - ${project.parent.version} - - - com.caucho - hessian - - - - - com.alibaba - dubbo-rpc-webservice - ${project.parent.version} - - - org.apache.cxf - cxf-rt-frontend-simple - - - org.apache.cxf - cxf-rt-transports-http - - - - - com.alibaba - dubbo-rpc-thrift - ${project.parent.version} - - - org.apache.thrift - libthrift - - - - - com.alibaba - dubbo-rpc-memcached - ${project.parent.version} - - - com.googlecode.xmemcached - xmemcached - - - - - com.alibaba - dubbo-rpc-redis - ${project.parent.version} - - - redis.clients - jedis - - - - - com.alibaba - dubbo-registry-default - ${project.parent.version} - - - com.alibaba - dubbo-registry-multicast - ${project.parent.version} - - - com.alibaba - dubbo-registry-zookeeper - ${project.parent.version} - - - org.apache.zookeeper - zookeeper - - - com.github.sgroschupf - zkclient - - - com.netflix.curator - curator-framework - - - - - com.alibaba - dubbo-registry-redis - ${project.parent.version} - - - redis.clients - jedis - - - - - com.alibaba - dubbo-monitor-default - ${project.parent.version} - - - com.alibaba - dubbo-container-spring - ${project.parent.version} - - - com.alibaba - dubbo-container-jetty - ${project.parent.version} - - - org.mortbay.jetty - jetty - - - - - com.alibaba - dubbo-container-log4j - ${project.parent.version} - - - com.alibaba - dubbo-container-logback - ${project.parent.version} - - - ch.qos.logback - logback-classic - - - - - - - - maven-source-plugin - - - attach-sources - none - - - - - maven-javadoc-plugin - - - attach-javadoc - deploy - - jar - - - - - public - UTF-8 - UTF-8 - UTF-8 - com.alibaba.com.* - - http://docs.oracle.com/javase/6/docs/api - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - true - true - - - com.alibaba:hessian-lite - com.alibaba:dubbo-common - com.alibaba:dubbo-remoting-api - com.alibaba:dubbo-remoting-netty - com.alibaba:dubbo-remoting-mina - com.alibaba:dubbo-remoting-grizzly - com.alibaba:dubbo-remoting-p2p - com.alibaba:dubbo-remoting-http - com.alibaba:dubbo-remoting-zookeeper - com.alibaba:dubbo-rpc-api - com.alibaba:dubbo-rpc-default - com.alibaba:dubbo-rpc-injvm - com.alibaba:dubbo-rpc-rmi - com.alibaba:dubbo-rpc-hessian - com.alibaba:dubbo-rpc-http - com.alibaba:dubbo-rpc-webservice - com.alibaba:dubbo-rpc-thrift - com.alibaba:dubbo-rpc-memcached - com.alibaba:dubbo-rpc-redis - com.alibaba:dubbo-filter-validation - com.alibaba:dubbo-filter-cache - com.alibaba:dubbo-cluster - com.alibaba:dubbo-registry-api - com.alibaba:dubbo-registry-default - com.alibaba:dubbo-registry-multicast - com.alibaba:dubbo-registry-zookeeper - com.alibaba:dubbo-registry-redis - com.alibaba:dubbo-monitor-api - com.alibaba:dubbo-monitor-default - com.alibaba:dubbo-config-api - com.alibaba:dubbo-config-spring - com.alibaba:dubbo-container-api - com.alibaba:dubbo-container-spring - com.alibaba:dubbo-container-jetty - com.alibaba:dubbo-container-log4j - com.alibaba:dubbo-container-logback - - - - - META-INF/dubbo/internal/com.alibaba.dubbo.common.compiler.Compiler - - - META-INF/dubbo/internal/com.alibaba.dubbo.common.extension.ExtensionFactory - - - META-INF/dubbo/internal/com.alibaba.dubbo.common.serialize.Serialization - - - META-INF/dubbo/internal/com.alibaba.dubbo.common.status.StatusChecker - - - META-INF/dubbo/internal/com.alibaba.dubbo.common.threadpool.ThreadPool - - - META-INF/dubbo/internal/com.alibaba.dubbo.remoting.Dispather - - - META-INF/dubbo/internal/com.alibaba.dubbo.remoting.Codec - - - META-INF/dubbo/internal/com.alibaba.dubbo.remoting.Transporter - - - META-INF/dubbo/internal/com.alibaba.dubbo.remoting.exchange.Exchanger - - - META-INF/dubbo/internal/com.alibaba.dubbo.remoting.http.HttpBinder - - - META-INF/dubbo/internal/com.alibaba.dubbo.remoting.p2p.Networker - - - META-INF/dubbo/internal/com.alibaba.dubbo.remoting.telnet.TelnetHandler - - - META-INF/dubbo/internal/com.alibaba.dubbo.remoting.zookeeper.ZookeeperTransporter - - - META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol - - - META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Filter - - - META-INF/dubbo/internal/com.alibaba.dubbo.rpc.InvokerListener - - - META-INF/dubbo/internal/com.alibaba.dubbo.rpc.ExporterListener - - - META-INF/dubbo/internal/com.alibaba.dubbo.rpc.ProxyFactory - - - META-INF/dubbo/internal/com.alibaba.dubbo.rpc.cluster.Cluster - - - META-INF/dubbo/internal/com.alibaba.dubbo.rpc.cluster.LoadBalance - - - META-INF/dubbo/internal/com.alibaba.dubbo.rpc.cluster.Merger - - - META-INF/dubbo/internal/com.alibaba.dubbo.rpc.cluster.RouterFactory - - - META-INF/dubbo/internal/com.alibaba.dubbo.rpc.cluster.ConfiguratorFactory - - - META-INF/dubbo/internal/com.alibaba.dubbo.container.Container - - - META-INF/dubbo/internal/com.alibaba.dubbo.container.page.PageHandler - - - META-INF/dubbo/internal/com.alibaba.dubbo.monitor.MonitorFactory - - - META-INF/dubbo/internal/com.alibaba.dubbo.registry.RegistryFactory - - - META-INF/dubbo/internal/com.alibaba.dubbo.validation.Validation - - - META-INF/dubbo/internal/com.alibaba.dubbo.cache.CacheFactory - - - - - - - - + + + 4.0.0 + + com.alibaba + dubbo-parent + 2.8.4 + + dubbo + jar + ${project.artifactId} + The all in one project of dubbo + + false + + + + com.alibaba + dubbo-config-api + ${project.parent.version} + + + org.mortbay.jetty + jetty + + + + + com.alibaba + dubbo-config-spring + ${project.parent.version} + + + com.alibaba + dubbo-remoting-netty + ${project.parent.version} + + + com.alibaba + dubbo-remoting-mina + ${project.parent.version} + + + org.apache.mina + mina-core + + + org.slf4j + slf4j-api + + + + + com.alibaba + dubbo-remoting-grizzly + ${project.parent.version} + + + org.glassfish.grizzly + grizzly-core + + + + + com.alibaba + dubbo-remoting-p2p + ${project.parent.version} + + + com.alibaba + dubbo-remoting-http + ${project.parent.version} + + + org.mortbay.jetty + jetty + + + org.apache.httpcomponents + httpclient + + + org.apache.tomcat.embed + tomcat-embed-core + + + org.apache.tomcat.embed + tomcat-embed-logging-juli + + + + + com.alibaba + dubbo-rpc-default + ${project.parent.version} + + + com.alibaba + dubbo-rpc-injvm + ${project.parent.version} + + + com.alibaba + dubbo-rpc-rmi + ${project.parent.version} + + + com.alibaba + dubbo-rpc-hessian + ${project.parent.version} + + + com.caucho + hessian + + + + + com.alibaba + dubbo-rpc-http + ${project.parent.version} + + + com.caucho + hessian + + + + + com.alibaba + dubbo-rpc-webservice + ${project.parent.version} + + + org.apache.cxf + cxf-rt-frontend-simple + + + org.apache.cxf + cxf-rt-transports-http + + + + + com.alibaba + dubbo-rpc-thrift + ${project.parent.version} + + + org.apache.thrift + libthrift + + + + + com.alibaba + dubbo-rpc-memcached + ${project.parent.version} + + + com.googlecode.xmemcached + xmemcached + + + + + com.alibaba + dubbo-rpc-redis + ${project.parent.version} + + + redis.clients + jedis + + + + + com.alibaba + dubbo-rpc-rest + ${project.parent.version} + + + org.jboss.resteasy + resteasy-jaxrs + + + org.jboss.resteasy + resteasy-client + + + org.jboss.resteasy + resteasy-netty + + + org.jboss.resteasy + resteasy-jdk-http + + + org.jboss.resteasy + resteasy-undertow + + + io.undertow + undertow-servlet + + + io.undertow + undertow-core + + + org.jboss.resteasy + resteasy-jackson-provider + + + org.jboss.resteasy + resteasy-jaxb-provider + + + javax.validation + validation-api + + + + + com.alibaba + dubbo-registry-default + ${project.parent.version} + + + com.alibaba + dubbo-registry-multicast + ${project.parent.version} + + + com.alibaba + dubbo-registry-zookeeper + ${project.parent.version} + + + org.apache.zookeeper + zookeeper + + + com.github.sgroschupf + zkclient + + + com.netflix.curator + curator-framework + + + + + com.alibaba + dubbo-registry-redis + ${project.parent.version} + + + redis.clients + jedis + + + + + com.alibaba + dubbo-monitor-default + ${project.parent.version} + + + com.alibaba + dubbo-container-spring + ${project.parent.version} + + + com.alibaba + dubbo-container-javaconfig + ${project.parent.version} + + + com.alibaba + dubbo-container-jetty + ${project.parent.version} + + + org.mortbay.jetty + jetty + + + + + com.alibaba + dubbo-container-log4j + ${project.parent.version} + + + com.alibaba + dubbo-container-logback + ${project.parent.version} + + + ch.qos.logback + logback-classic + + + + + + + + maven-source-plugin + + + attach-sources + package + + jar-no-fork + + + + + + maven-javadoc-plugin + + + attach-javadoc + deploy + + jar + + + + + public + UTF-8 + UTF-8 + UTF-8 + com.alibaba.com.* + + http://docs.oracle.com/javase/6/docs/api + + + + + org.apache.maven.plugins + maven-shade-plugin + 1.4 + + + package + + shade + + + true + true + + + com.alibaba:hessian-lite + com.alibaba:dubbo-common + com.alibaba:dubbo-remoting-api + com.alibaba:dubbo-remoting-netty + com.alibaba:dubbo-remoting-mina + com.alibaba:dubbo-remoting-grizzly + com.alibaba:dubbo-remoting-p2p + com.alibaba:dubbo-remoting-http + com.alibaba:dubbo-remoting-zookeeper + com.alibaba:dubbo-rpc-api + com.alibaba:dubbo-rpc-default + com.alibaba:dubbo-rpc-injvm + com.alibaba:dubbo-rpc-rmi + com.alibaba:dubbo-rpc-hessian + com.alibaba:dubbo-rpc-http + com.alibaba:dubbo-rpc-webservice + com.alibaba:dubbo-rpc-thrift + com.alibaba:dubbo-rpc-memcached + com.alibaba:dubbo-rpc-redis + com.alibaba:dubbo-rpc-rest + com.alibaba:dubbo-filter-validation + com.alibaba:dubbo-filter-cache + com.alibaba:dubbo-cluster + com.alibaba:dubbo-registry-api + com.alibaba:dubbo-registry-default + com.alibaba:dubbo-registry-multicast + com.alibaba:dubbo-registry-zookeeper + com.alibaba:dubbo-registry-redis + com.alibaba:dubbo-monitor-api + com.alibaba:dubbo-monitor-default + com.alibaba:dubbo-config-api + com.alibaba:dubbo-config-spring + com.alibaba:dubbo-container-api + com.alibaba:dubbo-container-spring + com.alibaba:dubbo-container-javaconfig + com.alibaba:dubbo-container-jetty + com.alibaba:dubbo-container-log4j + com.alibaba:dubbo-container-logback + + + + + META-INF/dubbo/internal/com.alibaba.dubbo.common.compiler.Compiler + + + META-INF/dubbo/internal/com.alibaba.dubbo.common.extension.ExtensionFactory + + + META-INF/dubbo/internal/com.alibaba.dubbo.common.serialize.Serialization + + + META-INF/dubbo/internal/com.alibaba.dubbo.common.status.StatusChecker + + + META-INF/dubbo/internal/com.alibaba.dubbo.common.threadpool.ThreadPool + + + META-INF/dubbo/internal/com.alibaba.dubbo.remoting.Dispatcher + + + META-INF/dubbo/internal/com.alibaba.dubbo.remoting.Codec2 + + + META-INF/dubbo/internal/com.alibaba.dubbo.remoting.Transporter + + + META-INF/dubbo/internal/com.alibaba.dubbo.remoting.exchange.Exchanger + + + META-INF/dubbo/internal/com.alibaba.dubbo.remoting.http.HttpBinder + + + META-INF/dubbo/internal/com.alibaba.dubbo.remoting.p2p.Networker + + + META-INF/dubbo/internal/com.alibaba.dubbo.remoting.telnet.TelnetHandler + + + META-INF/dubbo/internal/com.alibaba.dubbo.remoting.zookeeper.ZookeeperTransporter + + + META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol + + + META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Filter + + + META-INF/dubbo/internal/com.alibaba.dubbo.rpc.InvokerListener + + + META-INF/dubbo/internal/com.alibaba.dubbo.rpc.ExporterListener + + + META-INF/dubbo/internal/com.alibaba.dubbo.rpc.ProxyFactory + + + META-INF/dubbo/internal/com.alibaba.dubbo.rpc.cluster.Cluster + + + META-INF/dubbo/internal/com.alibaba.dubbo.rpc.cluster.LoadBalance + + + META-INF/dubbo/internal/com.alibaba.dubbo.rpc.cluster.Merger + + + META-INF/dubbo/internal/com.alibaba.dubbo.rpc.cluster.RouterFactory + + + META-INF/dubbo/internal/com.alibaba.dubbo.rpc.cluster.ConfiguratorFactory + + + META-INF/dubbo/internal/com.alibaba.dubbo.container.Container + + + META-INF/dubbo/internal/com.alibaba.dubbo.container.page.PageHandler + + + META-INF/dubbo/internal/com.alibaba.dubbo.monitor.MonitorFactory + + + META-INF/dubbo/internal/com.alibaba.dubbo.registry.RegistryFactory + + + META-INF/dubbo/internal/com.alibaba.dubbo.validation.Validation + + + META-INF/dubbo/internal/com.alibaba.dubbo.cache.CacheFactory + + + META-INF/dubbo/internal/com.alibaba.dubbo.common.store.DataStore + + + META-INF/dubbo/internal/com.alibaba.dubbo.common.logger.LoggerAdapter + + + + + + + + \ No newline at end of file diff --git a/dubbo/readme.txt b/dubbo/readme.txt new file mode 100644 index 000000000000..fed863d17bed --- /dev/null +++ b/dubbo/readme.txt @@ -0,0 +1,14 @@ + +޸ע⣺ + +1) µģ飬ҪPOMmaven-shade-plugin + +2) µչ㣬ҪPOMmaven-shade-plugin + + չļ + +$ find . -wholename */META-INF/dubbo/* -type f | grep -vF /test/ | awk -F/ '{print $NF}' | sort -u +com.alibaba.dubbo.cache.CacheFactory +com.alibaba.dubbo.common.compiler.Compiler +com.alibaba.dubbo.common.extension.ExtensionFactory +...and so on... diff --git a/hessian-lite/pom.xml b/hessian-lite/pom.xml new file mode 100644 index 000000000000..c377884a45e9 --- /dev/null +++ b/hessian-lite/pom.xml @@ -0,0 +1,15 @@ + + + 4.0.0 + + com.alibaba + dubbo-parent + 2.8.4 + + hessian-lite + jar + 3.2.1-fixed-2 + Hessian Lite(Alibaba embed version) + diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/HessianException.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/HessianException.java new file mode 100644 index 000000000000..8b08c3de46e3 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/HessianException.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian; + +/** + * Base runtime exception for Hessian exceptions. + */ +public class HessianException extends RuntimeException { + /** + * Zero-arg constructor. + */ + public HessianException() + { + } + + /** + * Create the exception. + */ + public HessianException(String message) + { + super(message); + } + + /** + * Create the exception. + */ + public HessianException(String message, Throwable rootCause) + { + super(message, rootCause); + } + + /** + * Create the exception. + */ + public HessianException(Throwable rootCause) + { + super(rootCause); + } +} 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 new file mode 100644 index 000000000000..802b2ca37b96 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractDeserializer.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; + +/** + * Deserializing an object. + */ +abstract public class AbstractDeserializer implements Deserializer { + public Class getType() + { + return Object.class; + } + + public Object readObject(AbstractHessianInput in) + throws IOException + { + Object obj = in.readObject(); + + String className = getClass().getName(); + + if (obj != null) + throw error(className + ": unexpected object " + obj.getClass().getName() + " (" + obj + ")"); + else + throw error(className + ": unexpected null value"); + } + + public Object readList(AbstractHessianInput in, int length) + throws IOException + { + throw new UnsupportedOperationException(String.valueOf(this)); + } + + public Object readLengthList(AbstractHessianInput in, int length) + throws IOException + { + throw new UnsupportedOperationException(String.valueOf(this)); + } + + public Object readMap(AbstractHessianInput in) + throws IOException + { + Object obj = in.readObject(); + + String className = getClass().getName(); + + if (obj != null) + throw error(className + ": unexpected object " + obj.getClass().getName() + " (" + obj + ")"); + else + throw error(className + ": unexpected null value"); + } + + public Object readObject(AbstractHessianInput in, String []fieldNames) + throws IOException + { + throw new UnsupportedOperationException(String.valueOf(this)); + } + + protected HessianProtocolException error(String msg) + { + return new HessianProtocolException(msg); + } + + protected String codeName(int ch) + { + if (ch < 0) + return "end of file"; + else + return "0x" + Integer.toHexString(ch & 0xff); + } +} 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 new file mode 100644 index 000000000000..6e1548f8aeda --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractHessianInput.java @@ -0,0 +1,442 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; + +/** + * Abstract base class for Hessian requests. Hessian users should only + * need to use the methods in this class. + * + *

+ * AbstractHessianInput in = ...; // get input
+ * String value;
+ *
+ * in.startReply();         // read reply header
+ * value = in.readString(); // read string value
+ * in.completeReply();      // read reply footer
+ * 
+ */ +abstract public class AbstractHessianInput { + private HessianRemoteResolver resolver; + + /** + * Initialize the Hessian stream with the underlying input stream. + */ + public void init(InputStream is) + { + } + + /** + * Returns the call's method + */ + abstract public String getMethod(); + + /** + * Sets the resolver used to lookup remote objects. + */ + public void setRemoteResolver(HessianRemoteResolver resolver) + { + this.resolver = resolver; + } + + /** + * Sets the resolver used to lookup remote objects. + */ + public HessianRemoteResolver getRemoteResolver() + { + return resolver; + } + + /** + * Sets the serializer factory. + */ + public void setSerializerFactory(SerializerFactory ser) + { + } + + /** + * Reads the call + * + *
+   * c major minor
+   * 
+ */ + abstract public int readCall() + throws IOException; + + /** + * For backward compatibility with HessianSkeleton + */ + public void skipOptionalCall() + throws IOException + { + } + + /** + * Reads a header, returning null if there are no headers. + * + *
+   * H b16 b8 value
+   * 
+ */ + abstract public String readHeader() + throws IOException; + + /** + * Starts reading the call + * + *

A successful completion will have a single value: + * + *

+   * m b16 b8 method
+   * 
+ */ + abstract public String readMethod() + throws IOException; + + /** + * Reads the number of method arguments + * + * @return -1 for a variable length (hessian 1.0) + */ + public int readMethodArgLength() + throws IOException + { + return -1; + } + + /** + * Starts reading the call, including the headers. + * + *

The call expects the following protocol data + * + *

+   * c major minor
+   * m b16 b8 method
+   * 
+ */ + abstract public void startCall() + throws IOException; + + /** + * Completes reading the call + * + *

The call expects the following protocol data + * + *

+   * Z
+   * 
+ */ + abstract public void completeCall() + throws IOException; + + /** + * Reads a reply as an object. + * If the reply has a fault, throws the exception. + */ + abstract public Object readReply(Class expectedClass) + throws Throwable; + + /** + * Starts reading the reply + * + *

A successful completion will have a single value: + * + *

+   * r
+   * v
+   * 
+ */ + abstract public void startReply() + throws Throwable; + + /** + * Completes reading the call + * + *

A successful completion will have a single value: + * + *

+   * z
+   * 
+ */ + abstract public void completeReply() + throws IOException; + + /** + * Reads a boolean + * + *
+   * T
+   * F
+   * 
+ */ + abstract public boolean readBoolean() + throws IOException; + + /** + * Reads a null + * + *
+   * N
+   * 
+ */ + abstract public void readNull() + throws IOException; + + /** + * Reads an integer + * + *
+   * I b32 b24 b16 b8
+   * 
+ */ + abstract public int readInt() + throws IOException; + + /** + * Reads a long + * + *
+   * L b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ */ + abstract public long readLong() + throws IOException; + + /** + * Reads a double. + * + *
+   * D b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ */ + abstract public double readDouble() + throws IOException; + + /** + * Reads a date. + * + *
+   * T b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ */ + abstract public long readUTCDate() + throws IOException; + + /** + * Reads a string encoded in UTF-8 + * + *
+   * s b16 b8 non-final string chunk
+   * S b16 b8 final string chunk
+   * 
+ */ + abstract public String readString() + throws IOException; + + /** + * Reads an XML node encoded in UTF-8 + * + *
+   * x b16 b8 non-final xml chunk
+   * X b16 b8 final xml chunk
+   * 
+ */ + public org.w3c.dom.Node readNode() + throws IOException + { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + /** + * Starts reading a string. All the characters must be read before + * calling the next method. The actual characters will be read with + * the reader's read() or read(char [], int, int). + * + *
+   * s b16 b8 non-final string chunk
+   * S b16 b8 final string chunk
+   * 
+ */ + abstract public Reader getReader() + throws IOException; + + /** + * Starts reading a byte array using an input stream. All the bytes + * must be read before calling the following method. + * + *
+   * b b16 b8 non-final binary chunk
+   * B b16 b8 final binary chunk
+   * 
+ */ + abstract public InputStream readInputStream() + throws IOException; + + /** + * Reads a byte array. + * + *
+   * b b16 b8 non-final binary chunk
+   * B b16 b8 final binary chunk
+   * 
+ */ + abstract public byte []readBytes() + throws IOException; + + /** + * Reads an arbitrary object from the input stream. + * + * @param expectedClass the expected class if the protocol doesn't supply it. + */ + abstract public Object readObject(Class expectedClass) + throws IOException; + + /** + * Reads an arbitrary object from the input stream. + */ + abstract public Object readObject() + throws IOException; + + /** + * Reads a remote object reference to the stream. The type is the + * type of the remote interface. + * + *
+   * 'r' 't' b16 b8 type url
+   * 
+ */ + abstract public Object readRemote() + throws IOException; + + /** + * Reads a reference + * + *
+   * R b32 b24 b16 b8
+   * 
+ */ + abstract public Object readRef() + throws IOException; + + /** + * Adds an object reference. + */ + abstract public int addRef(Object obj) + throws IOException; + + /** + * Sets an object reference. + */ + abstract public void setRef(int i, Object obj) + throws IOException; + + /** + * Resets the references for streaming. + */ + public void resetReferences() + { + } + + /** + * Reads the start of a list + */ + abstract public int readListStart() + throws IOException; + + /** + * Reads the length of a list. + */ + abstract public int readLength() + throws IOException; + + /** + * Reads the start of a map + */ + abstract public int readMapStart() + throws IOException; + + /** + * Reads an object type. + */ + abstract public String readType() + throws IOException; + + /** + * Returns true if the data has ended. + */ + abstract public boolean isEnd() + throws IOException; + + /** + * Read the end byte + */ + abstract public void readEnd() + throws IOException; + + /** + * Read the end byte + */ + abstract public void readMapEnd() + throws IOException; + + /** + * Read the end byte + */ + abstract public void readListEnd() + throws IOException; + + public void close() + throws IOException + { + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractHessianOutput.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractHessianOutput.java new file mode 100644 index 000000000000..f61732f54df2 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractHessianOutput.java @@ -0,0 +1,531 @@ +/* + * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * Abstract output stream for Hessian requests. + * + *
+ * OutputStream os = ...; // from http connection
+ * AbstractOutput out = new HessianSerializerOutput(os);
+ * String value;
+ *
+ * out.startCall("hello");  // start hello call
+ * out.writeString("arg1"); // write a string argument
+ * out.completeCall();      // complete the call
+ * 
+ */ +abstract public class AbstractHessianOutput { + // serializer factory + protected SerializerFactory _serializerFactory; + + /** + * Sets the serializer factory. + */ + public void setSerializerFactory(SerializerFactory factory) + { + _serializerFactory = factory; + } + + /** + * Gets the serializer factory. + */ + public SerializerFactory getSerializerFactory() + { + return _serializerFactory; + } + + /** + * Gets the serializer factory. + */ + public final SerializerFactory findSerializerFactory() + { + SerializerFactory factory = _serializerFactory; + + if (factory == null) + _serializerFactory = factory = new SerializerFactory(); + + return factory; + } + + /** + * Initialize the output with a new underlying stream. + */ + public void init(OutputStream os) + { + } + + /** + * Writes a complete method call. + */ + public void call(String method, Object []args) + throws IOException + { + int length = args != null ? args.length : 0; + + startCall(method, length); + + for (int i = 0; i < length; i++) + writeObject(args[i]); + + completeCall(); + } + + /** + * Starts the method call: + * + *
+   * C
+   * 
+ * + * @param method the method name to call. + */ + abstract public void startCall() + throws IOException; + + /** + * Starts the method call: + * + *
+   * C string int
+   * 
+ * + * @param method the method name to call. + */ + abstract public void startCall(String method, int length) + throws IOException; + + /** + * For Hessian 2.0, use the Header envelope instead + * + * @deprecated + */ + public void writeHeader(String name) + throws IOException + { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + /** + * Writes the method tag. + * + *
+   * string
+   * 
+ * + * @param method the method name to call. + */ + abstract public void writeMethod(String method) + throws IOException; + + /** + * Completes the method call: + * + *
+   * 
+ */ + abstract public void completeCall() + throws IOException; + + /** + * Writes a boolean value to the stream. The boolean will be written + * with the following syntax: + * + *
+   * T
+   * F
+   * 
+ * + * @param value the boolean value to write. + */ + abstract public void writeBoolean(boolean value) + throws IOException; + + /** + * Writes an integer value to the stream. The integer will be written + * with the following syntax: + * + *
+   * I b32 b24 b16 b8
+   * 
+ * + * @param value the integer value to write. + */ + abstract public void writeInt(int value) + throws IOException; + + /** + * Writes a long value to the stream. The long will be written + * with the following syntax: + * + *
+   * L b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ * + * @param value the long value to write. + */ + abstract public void writeLong(long value) + throws IOException; + + /** + * Writes a double value to the stream. The double will be written + * with the following syntax: + * + *
+   * D b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ * + * @param value the double value to write. + */ + abstract public void writeDouble(double value) + throws IOException; + + /** + * Writes a date to the stream. + * + *
+   * T  b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ * + * @param time the date in milliseconds from the epoch in UTC + */ + abstract public void writeUTCDate(long time) + throws IOException; + + /** + * Writes a null value to the stream. + * The null will be written with the following syntax + * + *
+   * N
+   * 
+ * + * @param value the string value to write. + */ + abstract public void writeNull() + throws IOException; + + /** + * Writes a string value to the stream using UTF-8 encoding. + * The string will be written with the following syntax: + * + *
+   * S b16 b8 string-value
+   * 
+ * + * If the value is null, it will be written as + * + *
+   * N
+   * 
+ * + * @param value the string value to write. + */ + abstract public void writeString(String value) + throws IOException; + + /** + * Writes a string value to the stream using UTF-8 encoding. + * The string will be written with the following syntax: + * + *
+   * S b16 b8 string-value
+   * 
+ * + * If the value is null, it will be written as + * + *
+   * N
+   * 
+ * + * @param value the string value to write. + */ + abstract public void writeString(char []buffer, int offset, int length) + throws IOException; + + /** + * Writes a byte array to the stream. + * The array will be written with the following syntax: + * + *
+   * B b16 b18 bytes
+   * 
+ * + * If the value is null, it will be written as + * + *
+   * N
+   * 
+ * + * @param value the string value to write. + */ + abstract public void writeBytes(byte []buffer) + throws IOException; + /** + * Writes a byte array to the stream. + * The array will be written with the following syntax: + * + *
+   * B b16 b18 bytes
+   * 
+ * + * If the value is null, it will be written as + * + *
+   * N
+   * 
+ * + * @param value the string value to write. + */ + abstract public void writeBytes(byte []buffer, int offset, int length) + throws IOException; + + /** + * Writes a byte buffer to the stream. + */ + abstract public void writeByteBufferStart() + throws IOException; + + /** + * Writes a byte buffer to the stream. + * + *
+   * b b16 b18 bytes
+   * 
+ * + * @param value the string value to write. + */ + abstract public void writeByteBufferPart(byte []buffer, + int offset, + int length) + throws IOException; + + /** + * Writes the last chunk of a byte buffer to the stream. + * + *
+   * b b16 b18 bytes
+   * 
+ * + * @param value the string value to write. + */ + abstract public void writeByteBufferEnd(byte []buffer, + int offset, + int length) + throws IOException; + + /** + * Writes a reference. + * + *
+   * Q int
+   * 
+ * + * @param value the integer value to write. + */ + abstract protected void writeRef(int value) + throws IOException; + + /** + * Removes a reference. + */ + abstract public boolean removeRef(Object obj) + throws IOException; + + /** + * Replaces a reference from one object to another. + */ + abstract public boolean replaceRef(Object oldRef, Object newRef) + throws IOException; + + /** + * Adds an object to the reference list. If the object already exists, + * writes the reference, otherwise, the caller is responsible for + * the serialization. + * + *
+   * R b32 b24 b16 b8
+   * 
+ * + * @param object the object to add as a reference. + * + * @return true if the object has already been written. + */ + abstract public boolean addRef(Object object) + throws IOException; + + /** + * Resets the references for streaming. + */ + public void resetReferences() + { + } + + /** + * Writes a generic object to the output stream. + */ + abstract public void writeObject(Object object) + throws IOException; + + /** + * Writes the list header to the stream. List writers will call + * writeListBegin followed by the list contents and then + * call writeListEnd. + * + *
+   * V
+   *   x13 java.util.ArrayList   # type
+   *   x93                       # length=3
+   *   x91                       # 1
+   *   x92                       # 2
+   *   x93                       # 3
+   * </list>
+   * 
+ */ + abstract public boolean writeListBegin(int length, String type) + throws IOException; + + /** + * Writes the tail of the list to the stream. + */ + abstract public void writeListEnd() + throws IOException; + + /** + * Writes the map header to the stream. Map writers will call + * writeMapBegin followed by the map contents and then + * call writeMapEnd. + * + *
+   * M type ( )* Z
+   * 
+ */ + abstract public void writeMapBegin(String type) + throws IOException; + + /** + * Writes the tail of the map to the stream. + */ + abstract public void writeMapEnd() + throws IOException; + + /** + * Writes the object header to the stream (for Hessian 2.0), or a + * Map for Hessian 1.0. Object writers will call + * writeObjectBegin followed by the map contents and then + * call writeObjectEnd. + * + *
+   * C type int *
+   * C int *
+   * 
+ * + * @return true if the object has already been defined. + */ + public int writeObjectBegin(String type) + throws IOException + { + writeMapBegin(type); + + return -2; + } + + /** + * Writes the end of the class. + */ + public void writeClassFieldLength(int len) + throws IOException + { + } + + /** + * Writes the tail of the object to the stream. + */ + public void writeObjectEnd() + throws IOException + { + } + + public void writeReply(Object o) + throws IOException + { + startReply(); + writeObject(o); + completeReply(); + } + + + public void startReply() + throws IOException + { + } + + public void completeReply() + throws IOException + { + } + + public void writeFault(String code, String message, Object detail) + throws IOException + { + } + + public void flush() + throws IOException + { + } + + public void close() + throws IOException + { + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractHessianResolver.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractHessianResolver.java new file mode 100644 index 000000000000..ae42285c9838 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractHessianResolver.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; + +/** + * Looks up remote objects. The default just returns a HessianRemote object. + */ +public class AbstractHessianResolver implements HessianRemoteResolver { + /** + * Looks up a proxy object. + */ + public Object lookup(String type, String url) + throws IOException + { + return new HessianRemote(type, url); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractListDeserializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractListDeserializer.java new file mode 100644 index 000000000000..20318b9d6599 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractListDeserializer.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; + +/** + * Deserializing a JDK 1.2 Collection. + */ +public class AbstractListDeserializer extends AbstractDeserializer { + public Object readObject(AbstractHessianInput in) + throws IOException + { + Object obj = in.readObject(); + + if (obj != null) + throw error("expected list at " + obj.getClass().getName() + " (" + obj + ")"); + else + throw error("expected list at null"); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractMapDeserializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractMapDeserializer.java new file mode 100644 index 000000000000..7a90a7912ac5 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractMapDeserializer.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.util.HashMap; + +/** + * Serializing an object for known object types. + */ +public class AbstractMapDeserializer extends AbstractDeserializer { + + public Class getType() + { + return HashMap.class; + } + + public Object readObject(AbstractHessianInput in) + throws IOException + { + Object obj = in.readObject(); + + if (obj != null) + throw error("expected map/object at " + obj.getClass().getName() + " (" + obj + ")"); + else + throw error("expected map/object at null"); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractSerializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractSerializer.java new file mode 100644 index 000000000000..df450cf340a2 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractSerializer.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.util.logging.*; + +/** + * Serializing an object. + */ +abstract public class AbstractSerializer implements Serializer { + protected static final Logger log + = Logger.getLogger(AbstractSerializer.class.getName()); + + abstract public void writeObject(Object obj, AbstractHessianOutput out) + throws IOException; +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractSerializerFactory.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractSerializerFactory.java new file mode 100644 index 000000000000..cc66de7ce866 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractSerializerFactory.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +/** + * Factory for returning serialization methods. + */ +abstract public class AbstractSerializerFactory { + /** + * Returns the serializer for a class. + * + * @param cl the class of the object that needs to be serialized. + * + * @return a serializer object for the serialization. + */ + abstract public Serializer getSerializer(Class cl) + throws HessianProtocolException; + + /** + * Returns the deserializer for a class. + * + * @param cl the class of the object that needs to be deserialized. + * + * @return a deserializer object for the serialization. + */ + abstract public Deserializer getDeserializer(Class cl) + throws HessianProtocolException; +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ArrayDeserializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ArrayDeserializer.java new file mode 100644 index 000000000000..cf8fc6e7e20e --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ArrayDeserializer.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.lang.reflect.Array; +import java.util.ArrayList; + +/** + * Deserializing a Java array + */ +public class ArrayDeserializer extends AbstractListDeserializer { + private Class _componentType; + private Class _type; + + public ArrayDeserializer(Class componentType) + { + _componentType = componentType; + + if (_componentType != null) { + try { + _type = Array.newInstance(_componentType, 0).getClass(); + } catch (Exception e) { + } + } + + if (_type == null) + _type = Object[].class; + } + + public Class getType() + { + return _type; + } + + /** + * Reads the array. + */ + public Object readList(AbstractHessianInput in, int length) + throws IOException + { + if (length >= 0) { + Object []data = createArray(length); + + in.addRef(data); + + if (_componentType != null) { + for (int i = 0; i < data.length; i++) + data[i] = in.readObject(_componentType); + } + else { + for (int i = 0; i < data.length; i++) + data[i] = in.readObject(); + } + + in.readListEnd(); + + return data; + } + else { + ArrayList list = new ArrayList(); + + in.addRef(list); + + if (_componentType != null) { + while (! in.isEnd()) + list.add(in.readObject(_componentType)); + } + else { + while (! in.isEnd()) + list.add(in.readObject()); + } + + in.readListEnd(); + + Object []data = createArray(list.size()); + for (int i = 0; i < data.length; i++) + data[i] = list.get(i); + + return data; + } + } + + /** + * Reads the array. + */ + public Object readLengthList(AbstractHessianInput in, int length) + throws IOException + { + Object []data = createArray(length); + + in.addRef(data); + + if (_componentType != null) { + for (int i = 0; i < data.length; i++) + data[i] = in.readObject(_componentType); + } + else { + for (int i = 0; i < data.length; i++) + data[i] = in.readObject(); + } + + return data; + } + + protected Object []createArray(int length) + { + if (_componentType != null) + return (Object []) Array.newInstance(_componentType, length); + else + return new Object[length]; + } + + public String toString() + { + return "ArrayDeserializer[" + _componentType + "]"; + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ArraySerializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ArraySerializer.java new file mode 100644 index 000000000000..7bcfe90f84a0 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ArraySerializer.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; + +/** + * Serializing a Java array. + */ +public class ArraySerializer extends AbstractSerializer { + public void writeObject(Object obj, AbstractHessianOutput out) + throws IOException + { + if (out.addRef(obj)) + return; + + Object []array = (Object []) obj; + + boolean hasEnd = out.writeListBegin(array.length, + getArrayType(obj.getClass())); + + for (int i = 0; i < array.length; i++) + out.writeObject(array[i]); + + if (hasEnd) + out.writeListEnd(); + } + + /** + * Returns the <type> name for a <list>. + */ + private String getArrayType(Class cl) + { + if (cl.isArray()) + return '[' + getArrayType(cl.getComponentType()); + + String name = cl.getName(); + + if (name.equals("java.lang.String")) + return "string"; + else if (name.equals("java.lang.Object")) + return "object"; + else if (name.equals("java.util.Date")) + return "date"; + else + return name; + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/BasicDeserializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/BasicDeserializer.java new file mode 100644 index 000000000000..a0e860f69818 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/BasicDeserializer.java @@ -0,0 +1,608 @@ +/* + * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Date; + +/** + * Serializing an object for known object types. + */ +public class BasicDeserializer extends AbstractDeserializer { + public static final int NULL = BasicSerializer.NULL; + public static final int BOOLEAN = BasicSerializer.BOOLEAN; + public static final int BYTE = BasicSerializer.BYTE; + public static final int SHORT = BasicSerializer.SHORT; + public static final int INTEGER = BasicSerializer.INTEGER; + public static final int LONG = BasicSerializer.LONG; + public static final int FLOAT = BasicSerializer.FLOAT; + public static final int DOUBLE = BasicSerializer.DOUBLE; + public static final int CHARACTER = BasicSerializer.CHARACTER; + public static final int CHARACTER_OBJECT = BasicSerializer.CHARACTER_OBJECT; + public static final int STRING = BasicSerializer.STRING; + public static final int DATE = BasicSerializer.DATE; + public static final int NUMBER = BasicSerializer.NUMBER; + public static final int OBJECT = BasicSerializer.OBJECT; + + public static final int BOOLEAN_ARRAY = BasicSerializer.BOOLEAN_ARRAY; + public static final int BYTE_ARRAY = BasicSerializer.BYTE_ARRAY; + public static final int SHORT_ARRAY = BasicSerializer.SHORT_ARRAY; + public static final int INTEGER_ARRAY = BasicSerializer.INTEGER_ARRAY; + public static final int LONG_ARRAY = BasicSerializer.LONG_ARRAY; + public static final int FLOAT_ARRAY = BasicSerializer.FLOAT_ARRAY; + public static final int DOUBLE_ARRAY = BasicSerializer.DOUBLE_ARRAY; + public static final int CHARACTER_ARRAY = BasicSerializer.CHARACTER_ARRAY; + public static final int STRING_ARRAY = BasicSerializer.STRING_ARRAY; + public static final int OBJECT_ARRAY = BasicSerializer.OBJECT_ARRAY; + + private int _code; + + public BasicDeserializer(int code) + { + _code = code; + } + + public Class getType() + { + switch (_code) { + case NULL: + return void.class; + case BOOLEAN: + return Boolean.class; + case BYTE: + return Byte.class; + case SHORT: + return Short.class; + case INTEGER: + return Integer.class; + case LONG: + return Long.class; + case FLOAT: + return Float.class; + case DOUBLE: + return Double.class; + case CHARACTER: + return Character.class; + case CHARACTER_OBJECT: + return Character.class; + case STRING: + return String.class; + case DATE: + return Date.class; + case NUMBER: + return Number.class; + case OBJECT: + return Object.class; + + case BOOLEAN_ARRAY: + return boolean[].class; + case BYTE_ARRAY: + return byte[].class; + case SHORT_ARRAY: + return short[].class; + case INTEGER_ARRAY: + return int[].class; + case LONG_ARRAY: + return long[].class; + case FLOAT_ARRAY: + return float[].class; + case DOUBLE_ARRAY: + return double[].class; + case CHARACTER_ARRAY: + return char[].class; + case STRING_ARRAY: + return String[].class; + case OBJECT_ARRAY: + return Object[].class; + default: + throw new UnsupportedOperationException(); + } + } + + public Object readObject(AbstractHessianInput in) + throws IOException + { + switch (_code) { + case NULL: + // hessian/3490 + in.readObject(); + + return null; + + case BOOLEAN: + return Boolean.valueOf(in.readBoolean()); + + case BYTE: + return Byte.valueOf((byte) in.readInt()); + + case SHORT: + return Short.valueOf((short) in.readInt()); + + case INTEGER: + return Integer.valueOf(in.readInt()); + + case LONG: + return Long.valueOf(in.readLong()); + + case FLOAT: + return Float.valueOf((float) in.readDouble()); + + case DOUBLE: + return Double.valueOf(in.readDouble()); + + case STRING: + return in.readString(); + + case OBJECT: + return in.readObject(); + + case CHARACTER: + { + String s = in.readString(); + if (s == null || s.equals("")) + return Character.valueOf((char) 0); + else + return Character.valueOf(s.charAt(0)); + } + + case CHARACTER_OBJECT: + { + String s = in.readString(); + if (s == null || s.equals("")) + return null; + else + return Character.valueOf(s.charAt(0)); + } + + case DATE: + return new Date(in.readUTCDate()); + + case NUMBER: + return in.readObject(); + + case BYTE_ARRAY: + return in.readBytes(); + + case CHARACTER_ARRAY: + { + String s = in.readString(); + + if (s == null) + return null; + else { + int len = s.length(); + char []chars = new char[len]; + s.getChars(0, len, chars, 0); + return chars; + } + } + + case BOOLEAN_ARRAY: + case SHORT_ARRAY: + case INTEGER_ARRAY: + case LONG_ARRAY: + case FLOAT_ARRAY: + case DOUBLE_ARRAY: + case STRING_ARRAY: + { + int code = in.readListStart(); + + switch (code) { + case 'N': + return null; + + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x18: case 0x19: case 0x1a: case 0x1b: + case 0x1c: case 0x1d: case 0x1e: case 0x1f: + int length = code - 0x10; + in.readInt(); + + return readLengthList(in, length); + + default: + String type = in.readType(); + length = in.readLength(); + + return readList(in, length); + } + } + + default: + throw new UnsupportedOperationException(); + } + } + + public Object readList(AbstractHessianInput in, int length) + throws IOException + { + switch (_code) { + case BOOLEAN_ARRAY: { + if (length >= 0) { + boolean []data = new boolean[length]; + + in.addRef(data); + + for (int i = 0; i < data.length; i++) + data[i] = in.readBoolean(); + + in.readEnd(); + + return data; + } + else { + ArrayList list = new ArrayList(); + + while (! in.isEnd()) + list.add(Boolean.valueOf(in.readBoolean())); + + in.readEnd(); + + boolean []data = new boolean[list.size()]; + + in.addRef(data); + + for (int i = 0; i < data.length; i++) + data[i] = ((Boolean) list.get(i)).booleanValue(); + + return data; + } + } + + case SHORT_ARRAY: { + if (length >= 0) { + short []data = new short[length]; + + in.addRef(data); + + for (int i = 0; i < data.length; i++) + data[i] = (short) in.readInt(); + + in.readEnd(); + + return data; + } + else { + ArrayList list = new ArrayList(); + + while (! in.isEnd()) + list.add(Short.valueOf((short) in.readInt())); + + in.readEnd(); + + short []data = new short[list.size()]; + for (int i = 0; i < data.length; i++) + data[i] = ((Short) list.get(i)).shortValue(); + + in.addRef(data); + + return data; + } + } + + case INTEGER_ARRAY: { + if (length >= 0) { + int []data = new int[length]; + + in.addRef(data); + + for (int i = 0; i < data.length; i++) + data[i] = in.readInt(); + + in.readEnd(); + + return data; + } + else { + ArrayList list = new ArrayList(); + + while (! in.isEnd()) + list.add(Integer.valueOf(in.readInt())); + + + in.readEnd(); + + int []data = new int[list.size()]; + for (int i = 0; i < data.length; i++) + data[i] = ((Integer) list.get(i)).intValue(); + + in.addRef(data); + + return data; + } + } + + case LONG_ARRAY: { + if (length >= 0) { + long []data = new long[length]; + + in.addRef(data); + + for (int i = 0; i < data.length; i++) + data[i] = in.readLong(); + + in.readEnd(); + + return data; + } + else { + ArrayList list = new ArrayList(); + + while (! in.isEnd()) + list.add(Long.valueOf(in.readLong())); + + in.readEnd(); + + long []data = new long[list.size()]; + for (int i = 0; i < data.length; i++) + data[i] = ((Long) list.get(i)).longValue(); + + in.addRef(data); + + return data; + } + } + + case FLOAT_ARRAY: { + if (length >= 0) { + float []data = new float[length]; + in.addRef(data); + + for (int i = 0; i < data.length; i++) + data[i] = (float) in.readDouble(); + + in.readEnd(); + + return data; + } + else { + ArrayList list = new ArrayList(); + + while (! in.isEnd()) + list.add(new Float(in.readDouble())); + + in.readEnd(); + + float []data = new float[list.size()]; + for (int i = 0; i < data.length; i++) + data[i] = ((Float) list.get(i)).floatValue(); + + in.addRef(data); + + return data; + } + } + + case DOUBLE_ARRAY: { + if (length >= 0) { + double []data = new double[length]; + in.addRef(data); + + for (int i = 0; i < data.length; i++) + data[i] = in.readDouble(); + + in.readEnd(); + + return data; + } + else { + ArrayList list = new ArrayList(); + + while (! in.isEnd()) + list.add(new Double(in.readDouble())); + + in.readEnd(); + + double []data = new double[list.size()]; + in.addRef(data); + for (int i = 0; i < data.length; i++) + data[i] = ((Double) list.get(i)).doubleValue(); + + return data; + } + } + + case STRING_ARRAY: { + if (length >= 0) { + String []data = new String[length]; + in.addRef(data); + + for (int i = 0; i < data.length; i++) + data[i] = in.readString(); + + in.readEnd(); + + return data; + } + else { + ArrayList list = new ArrayList(); + + while (! in.isEnd()) + list.add(in.readString()); + + in.readEnd(); + + String []data = new String[list.size()]; + in.addRef(data); + for (int i = 0; i < data.length; i++) + data[i] = (String) list.get(i); + + return data; + } + } + + case OBJECT_ARRAY: { + if (length >= 0) { + Object []data = new Object[length]; + in.addRef(data); + + for (int i = 0; i < data.length; i++) + data[i] = in.readObject(); + + in.readEnd(); + + return data; + } + else { + ArrayList list = new ArrayList(); + + in.addRef(list); // XXX: potential issues here + + while (! in.isEnd()) + list.add(in.readObject()); + + in.readEnd(); + + Object []data = new Object[list.size()]; + for (int i = 0; i < data.length; i++) + data[i] = (Object) list.get(i); + + return data; + } + } + + default: + throw new UnsupportedOperationException(String.valueOf(this)); + } + } + + public Object readLengthList(AbstractHessianInput in, int length) + throws IOException + { + switch (_code) { + case BOOLEAN_ARRAY: { + boolean []data = new boolean[length]; + + in.addRef(data); + + for (int i = 0; i < data.length; i++) + data[i] = in.readBoolean(); + + return data; + } + + case SHORT_ARRAY: { + short []data = new short[length]; + + in.addRef(data); + + for (int i = 0; i < data.length; i++) + data[i] = (short) in.readInt(); + + return data; + } + + case INTEGER_ARRAY: { + int []data = new int[length]; + + in.addRef(data); + + for (int i = 0; i < data.length; i++) + data[i] = in.readInt(); + + return data; + } + + case LONG_ARRAY: { + long []data = new long[length]; + + in.addRef(data); + + for (int i = 0; i < data.length; i++) + data[i] = in.readLong(); + + return data; + } + + case FLOAT_ARRAY: { + float []data = new float[length]; + in.addRef(data); + + for (int i = 0; i < data.length; i++) + data[i] = (float) in.readDouble(); + + return data; + } + + case DOUBLE_ARRAY: { + double []data = new double[length]; + in.addRef(data); + + for (int i = 0; i < data.length; i++) + data[i] = in.readDouble(); + + return data; + } + + case STRING_ARRAY: { + String []data = new String[length]; + in.addRef(data); + + for (int i = 0; i < data.length; i++) + data[i] = in.readString(); + + return data; + } + + case OBJECT_ARRAY: { + Object []data = new Object[length]; + in.addRef(data); + + for (int i = 0; i < data.length; i++) + data[i] = in.readObject(); + + return data; + } + + default: + throw new UnsupportedOperationException(String.valueOf(this)); + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/BasicSerializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/BasicSerializer.java new file mode 100644 index 000000000000..2feb40b655db --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/BasicSerializer.java @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.util.Date; + +/** + * Serializing an object for known object types. + */ +public class BasicSerializer extends AbstractSerializer { + public static final int NULL = 0; + public static final int BOOLEAN = NULL + 1; + public static final int BYTE = BOOLEAN + 1; + public static final int SHORT = BYTE + 1; + public static final int INTEGER = SHORT + 1; + public static final int LONG = INTEGER + 1; + public static final int FLOAT = LONG + 1; + public static final int DOUBLE = FLOAT + 1; + public static final int CHARACTER = DOUBLE + 1; + public static final int CHARACTER_OBJECT = CHARACTER + 1; + public static final int STRING = CHARACTER_OBJECT + 1; + public static final int DATE = STRING + 1; + public static final int NUMBER = DATE + 1; + public static final int OBJECT = NUMBER + 1; + + public static final int BOOLEAN_ARRAY = OBJECT + 1; + public static final int BYTE_ARRAY = BOOLEAN_ARRAY + 1; + public static final int SHORT_ARRAY = BYTE_ARRAY + 1; + public static final int INTEGER_ARRAY = SHORT_ARRAY + 1; + public static final int LONG_ARRAY = INTEGER_ARRAY + 1; + public static final int FLOAT_ARRAY = LONG_ARRAY + 1; + public static final int DOUBLE_ARRAY = FLOAT_ARRAY + 1; + public static final int CHARACTER_ARRAY = DOUBLE_ARRAY + 1; + public static final int STRING_ARRAY = CHARACTER_ARRAY + 1; + public static final int OBJECT_ARRAY = STRING_ARRAY + 1; + + private int code; + + public BasicSerializer(int code) + { + this.code = code; + } + + public void writeObject(Object obj, AbstractHessianOutput out) + throws IOException + { + switch (code) { + case BOOLEAN: + out.writeBoolean(((Boolean) obj).booleanValue()); + break; + + case BYTE: + case SHORT: + case INTEGER: + out.writeInt(((Number) obj).intValue()); + break; + + case LONG: + out.writeLong(((Number) obj).longValue()); + break; + + case FLOAT: + case DOUBLE: + out.writeDouble(((Number) obj).doubleValue()); + break; + + case CHARACTER: + case CHARACTER_OBJECT: + out.writeString(String.valueOf(obj)); + break; + + case STRING: + out.writeString((String) obj); + break; + + case DATE: + out.writeUTCDate(((Date) obj).getTime()); + break; + + case BOOLEAN_ARRAY: + { + if (out.addRef(obj)) + return; + + boolean []data = (boolean []) obj; + boolean hasEnd = out.writeListBegin(data.length, "[boolean"); + for (int i = 0; i < data.length; i++) + out.writeBoolean(data[i]); + + if (hasEnd) + out.writeListEnd(); + + break; + } + + case BYTE_ARRAY: + { + byte []data = (byte []) obj; + out.writeBytes(data, 0, data.length); + break; + } + + case SHORT_ARRAY: + { + if (out.addRef(obj)) + return; + + short []data = (short []) obj; + boolean hasEnd = out.writeListBegin(data.length, "[short"); + + for (int i = 0; i < data.length; i++) + out.writeInt(data[i]); + + if (hasEnd) + out.writeListEnd(); + break; + } + + case INTEGER_ARRAY: + { + if (out.addRef(obj)) + return; + + int []data = (int []) obj; + + boolean hasEnd = out.writeListBegin(data.length, "[int"); + + for (int i = 0; i < data.length; i++) + out.writeInt(data[i]); + + if (hasEnd) + out.writeListEnd(); + + break; + } + + case LONG_ARRAY: + { + if (out.addRef(obj)) + return; + + long []data = (long []) obj; + + boolean hasEnd = out.writeListBegin(data.length, "[long"); + + for (int i = 0; i < data.length; i++) + out.writeLong(data[i]); + + if (hasEnd) + out.writeListEnd(); + break; + } + + case FLOAT_ARRAY: + { + if (out.addRef(obj)) + return; + + float []data = (float []) obj; + + boolean hasEnd = out.writeListBegin(data.length, "[float"); + + for (int i = 0; i < data.length; i++) + out.writeDouble(data[i]); + + if (hasEnd) + out.writeListEnd(); + break; + } + + case DOUBLE_ARRAY: + { + if (out.addRef(obj)) + return; + + double []data = (double []) obj; + boolean hasEnd = out.writeListBegin(data.length, "[double"); + + for (int i = 0; i < data.length; i++) + out.writeDouble(data[i]); + + if (hasEnd) + out.writeListEnd(); + break; + } + + case STRING_ARRAY: + { + if (out.addRef(obj)) + return; + + String []data = (String []) obj; + + boolean hasEnd = out.writeListBegin(data.length, "[string"); + + for (int i = 0; i < data.length; i++) { + out.writeString(data[i]); + } + + if (hasEnd) + out.writeListEnd(); + break; + } + + case CHARACTER_ARRAY: + { + char []data = (char []) obj; + out.writeString(data, 0, data.length); + break; + } + + case OBJECT_ARRAY: + { + if (out.addRef(obj)) + return; + + Object []data = (Object []) obj; + + boolean hasEnd = out.writeListBegin(data.length, "[object"); + + for (int i = 0; i < data.length; i++) { + out.writeObject(data[i]); + } + + if (hasEnd) + out.writeListEnd(); + break; + } + + case NULL: + out.writeNull(); + break; + + default: + throw new RuntimeException(code + " " + String.valueOf(obj.getClass())); + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/BeanDeserializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/BeanDeserializer.java new file mode 100644 index 000000000000..f669c70c6f56 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/BeanDeserializer.java @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.HashMap; + +/** + * Serializing an object for known object types. + */ +public class BeanDeserializer extends AbstractMapDeserializer { + private Class _type; + private HashMap _methodMap; + private Method _readResolve; + private Constructor _constructor; + private Object []_constructorArgs; + + public BeanDeserializer(Class cl) + { + _type = cl; + _methodMap = getMethodMap(cl); + + _readResolve = getReadResolve(cl); + + Constructor []constructors = cl.getConstructors(); + int bestLength = Integer.MAX_VALUE; + + for (int i = 0; i < constructors.length; i++) { + if (constructors[i].getParameterTypes().length < bestLength) { + _constructor = constructors[i]; + bestLength = _constructor.getParameterTypes().length; + } + } + + if (_constructor != null) { + _constructor.setAccessible(true); + Class []params = _constructor.getParameterTypes(); + _constructorArgs = new Object[params.length]; + for (int i = 0; i < params.length; i++) { + _constructorArgs[i] = getParamArg(params[i]); + } + } + } + + public Class getType() + { + return _type; + } + + public Object readMap(AbstractHessianInput in) + throws IOException + { + try { + Object obj = instantiate(); + + return readMap(in, obj); + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new IOExceptionWrapper(e); + } + } + + public Object readMap(AbstractHessianInput in, Object obj) + throws IOException + { + try { + int ref = in.addRef(obj); + + while (! in.isEnd()) { + Object key = in.readObject(); + + Method method = (Method) _methodMap.get(key); + + if (method != null) { + Object value = in.readObject(method.getParameterTypes()[0]); + + method.invoke(obj, new Object[] {value }); + } + else { + Object value = in.readObject(); + } + } + + in.readMapEnd(); + + Object resolve = resolve(obj); + + if (obj != resolve) + in.setRef(ref, resolve); + + return resolve; + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new IOExceptionWrapper(e); + } + } + + private Object resolve(Object obj) + { + // if there's a readResolve method, call it + try { + if (_readResolve != null) + return _readResolve.invoke(obj, new Object[0]); + } catch (Exception e) { + } + + return obj; + } + + protected Object instantiate() + throws Exception + { + return _constructor.newInstance(_constructorArgs); + } + + /** + * Returns the readResolve method + */ + protected Method getReadResolve(Class cl) + { + for (; cl != null; cl = cl.getSuperclass()) { + Method []methods = cl.getDeclaredMethods(); + + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + + if (method.getName().equals("readResolve") && + method.getParameterTypes().length == 0) + return method; + } + } + + return null; + } + + /** + * Creates a map of the classes fields. + */ + protected HashMap getMethodMap(Class cl) + { + HashMap methodMap = new HashMap(); + + for (; cl != null; cl = cl.getSuperclass()) { + Method []methods = cl.getDeclaredMethods(); + + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + + if (Modifier.isStatic(method.getModifiers())) + continue; + + String name = method.getName(); + + if (! name.startsWith("set")) + continue; + + Class []paramTypes = method.getParameterTypes(); + if (paramTypes.length != 1) + continue; + + if (! method.getReturnType().equals(void.class)) + continue; + + if (findGetter(methods, name, paramTypes[0]) == null) + continue; + + // XXX: could parameterize the handler to only deal with public + try { + method.setAccessible(true); + } catch (Throwable e) { + e.printStackTrace(); + } + + name = name.substring(3); + + int j = 0; + for (; j < name.length() && Character.isUpperCase(name.charAt(j)); j++) { + } + + if (j == 1) + name = name.substring(0, j).toLowerCase() + name.substring(j); + else if (j > 1) + name = name.substring(0, j - 1).toLowerCase() + name.substring(j - 1); + + + methodMap.put(name, method); + } + } + + return methodMap; + } + + /** + * Finds any matching setter. + */ + private Method findGetter(Method []methods, String setterName, Class arg) + { + String getterName = "get" + setterName.substring(3); + + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + + if (! method.getName().equals(getterName)) + continue; + + if (! method.getReturnType().equals(arg)) + continue; + + Class []params = method.getParameterTypes(); + + if (params.length == 0) + return method; + } + + return null; + } + + /** + * Creates a map of the classes fields. + */ + protected static Object getParamArg(Class cl) + { + if (! cl.isPrimitive()) + return null; + else if (boolean.class.equals(cl)) + return Boolean.FALSE; + else if (byte.class.equals(cl)) + return Byte.valueOf((byte) 0); + else if (short.class.equals(cl)) + return Short.valueOf((short) 0); + else if (char.class.equals(cl)) + return Character.valueOf((char) 0); + else if (int.class.equals(cl)) + return Integer.valueOf(0); + else if (long.class.equals(cl)) + return Long.valueOf(0); + else if (float.class.equals(cl)) + return Double.valueOf(0); + else if (double.class.equals(cl)) + return Double.valueOf(0); + else + throw new UnsupportedOperationException(); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/BeanSerializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/BeanSerializer.java new file mode 100644 index 000000000000..40dd16689163 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/BeanSerializer.java @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.logging.*; + +/** + * Serializing an object for known object types. + */ +public class BeanSerializer extends AbstractSerializer { + private static final Logger log + = Logger.getLogger(BeanSerializer.class.getName()); + + private static final Object []NULL_ARGS = new Object[0]; + private Method []_methods; + private String []_names; + + private Object _writeReplaceFactory; + private Method _writeReplace; + + public BeanSerializer(Class cl, ClassLoader loader) + { + introspectWriteReplace(cl, loader); + + ArrayList primitiveMethods = new ArrayList(); + ArrayList compoundMethods = new ArrayList(); + + for (; cl != null; cl = cl.getSuperclass()) { + Method []methods = cl.getDeclaredMethods(); + + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + + if (Modifier.isStatic(method.getModifiers())) + continue; + + if (method.getParameterTypes().length != 0) + continue; + + String name = method.getName(); + + if (! name.startsWith("get")) + continue; + + Class type = method.getReturnType(); + + if (type.equals(void.class)) + continue; + + if (findSetter(methods, name, type) == null) + continue; + + // XXX: could parameterize the handler to only deal with public + method.setAccessible(true); + + if (type.isPrimitive() + || type.getName().startsWith("java.lang.") + && ! type.equals(Object.class)) + primitiveMethods.add(method); + else + compoundMethods.add(method); + } + } + + ArrayList methodList = new ArrayList(); + methodList.addAll(primitiveMethods); + methodList.addAll(compoundMethods); + + Collections.sort(methodList, new MethodNameCmp()); + + _methods = new Method[methodList.size()]; + methodList.toArray(_methods); + + _names = new String[_methods.length]; + + for (int i = 0; i < _methods.length; i++) { + String name = _methods[i].getName(); + + name = name.substring(3); + + int j = 0; + for (; j < name.length() && Character.isUpperCase(name.charAt(j)); j++) { + } + + if (j == 1) + name = name.substring(0, j).toLowerCase() + name.substring(j); + else if (j > 1) + name = name.substring(0, j - 1).toLowerCase() + name.substring(j - 1); + + _names[i] = name; + } + } + + private void introspectWriteReplace(Class cl, ClassLoader loader) + { + try { + String className = cl.getName() + "HessianSerializer"; + + Class serializerClass = Class.forName(className, false, loader); + + Object serializerObject = serializerClass.newInstance(); + + Method writeReplace = getWriteReplace(serializerClass, cl); + + if (writeReplace != null) { + _writeReplaceFactory = serializerObject; + _writeReplace = writeReplace; + + return; + } + } catch (ClassNotFoundException e) { + } catch (Exception e) { + log.log(Level.FINER, e.toString(), e); + } + + _writeReplace = getWriteReplace(cl); + } + + /** + * Returns the writeReplace method + */ + protected Method getWriteReplace(Class cl) + { + for (; cl != null; cl = cl.getSuperclass()) { + Method []methods = cl.getDeclaredMethods(); + + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + + if (method.getName().equals("writeReplace") && + method.getParameterTypes().length == 0) + return method; + } + } + + return null; + } + + /** + * Returns the writeReplace method + */ + protected Method getWriteReplace(Class cl, Class param) + { + for (; cl != null; cl = cl.getSuperclass()) { + for (Method method : cl.getDeclaredMethods()) { + if (method.getName().equals("writeReplace") + && method.getParameterTypes().length == 1 + && param.equals(method.getParameterTypes()[0])) + return method; + } + } + + return null; + } + + public void writeObject(Object obj, AbstractHessianOutput out) + throws IOException + { + if (out.addRef(obj)) + return; + + Class cl = obj.getClass(); + + try { + if (_writeReplace != null) { + Object repl; + + if (_writeReplaceFactory != null) + repl = _writeReplace.invoke(_writeReplaceFactory, obj); + else + repl = _writeReplace.invoke(obj); + + out.removeRef(obj); + + out.writeObject(repl); + + out.replaceRef(repl, obj); + + return; + } + } catch (Exception e) { + log.log(Level.FINER, e.toString(), e); + } + + int ref = out.writeObjectBegin(cl.getName()); + + if (ref < -1) { + // Hessian 1.1 uses a map + + for (int i = 0; i < _methods.length; i++) { + Method method = _methods[i]; + Object value = null; + + try { + value = _methods[i].invoke(obj, (Object []) null); + } catch (Exception e) { + log.log(Level.FINE, e.toString(), e); + } + + out.writeString(_names[i]); + + out.writeObject(value); + } + + out.writeMapEnd(); + } + else { + if (ref == -1) { + out.writeInt(_names.length); + + for (int i = 0; i < _names.length; i++) + out.writeString(_names[i]); + + out.writeObjectBegin(cl.getName()); + } + + for (int i = 0; i < _methods.length; i++) { + Method method = _methods[i]; + Object value = null; + + try { + value = _methods[i].invoke(obj, (Object []) null); + } catch (Exception e) { + log.log(Level.FINER, e.toString(), e); + } + + out.writeObject(value); + } + } + } + + /** + * Finds any matching setter. + */ + private Method findSetter(Method []methods, String getterName, Class arg) + { + String setterName = "set" + getterName.substring(3); + + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + + if (! method.getName().equals(setterName)) + continue; + + if (! method.getReturnType().equals(void.class)) + continue; + + Class []params = method.getParameterTypes(); + + if (params.length == 1 && params[0].equals(arg)) + return method; + } + + return null; + } + + static class MethodNameCmp implements Comparator { + public int compare(Method a, Method b) + { + return a.getName().compareTo(b.getName()); + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/BeanSerializerFactory.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/BeanSerializerFactory.java new file mode 100644 index 000000000000..18a7f0323e26 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/BeanSerializerFactory.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +/** + * Factory for returning serialization methods. + */ +public class BeanSerializerFactory extends SerializerFactory { + /** + * Returns the default serializer for a class that isn't matched + * directly. Application can override this method to produce + * bean-style serialization instead of field serialization. + * + * @param cl the class of the object that needs to be serialized. + * + * @return a serializer object for the serialization. + */ + protected Serializer getDefaultSerializer(Class cl) + { + return new BeanSerializer(cl, getClassLoader()); + } + + /** + * Returns the default deserializer for a class that isn't matched + * directly. Application can override this method to produce + * bean-style serialization instead of field serialization. + * + * @param cl the class of the object that needs to be serialized. + * + * @return a serializer object for the serialization. + */ + protected Deserializer getDefaultDeserializer(Class cl) + { + return new BeanDeserializer(cl); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/BigIntegerDeserializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/BigIntegerDeserializer.java new file mode 100644 index 000000000000..e718bef3dbb5 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/BigIntegerDeserializer.java @@ -0,0 +1,18 @@ +package com.alibaba.com.caucho.hessian.io; + +import java.math.BigInteger; + +/** + * @author kimi + */ +public class BigIntegerDeserializer extends JavaDeserializer { + + public BigIntegerDeserializer() { + super(BigInteger.class); + } + + @Override + protected Object instantiate() throws Exception { + return new BigInteger("0"); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/CalendarHandle.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/CalendarHandle.java new file mode 100644 index 000000000000..ed752664dc3a --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/CalendarHandle.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +/** + * Handle for a calendar object. + */ +public class CalendarHandle implements java.io.Serializable, HessianHandle { + private Class type; + private Date date; + + public CalendarHandle() + { + } + + public CalendarHandle(Class type, long time) + { + if (! GregorianCalendar.class.equals(type)) + this.type = type; + + this.date = new Date(time); + } + + private Object readResolve() + { + try { + Calendar cal; + + if (this.type != null) + cal = (Calendar) this.type.newInstance(); + else + cal = new GregorianCalendar(); + + cal.setTimeInMillis(this.date.getTime()); + + return cal; + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/CalendarSerializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/CalendarSerializer.java new file mode 100644 index 000000000000..bc48f262ff78 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/CalendarSerializer.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.util.Calendar; + +/** + * Serializing a calendar. + */ +public class CalendarSerializer extends AbstractSerializer { + private static CalendarSerializer SERIALIZER = new CalendarSerializer(); + + public static CalendarSerializer create() + { + return SERIALIZER; + } + + public void writeObject(Object obj, AbstractHessianOutput out) + throws IOException + { + if (obj == null) + out.writeNull(); + else { + Calendar cal = (Calendar) obj; + + out.writeObject(new CalendarHandle(cal.getClass(), + cal.getTimeInMillis())); + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ClassDeserializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ClassDeserializer.java new file mode 100644 index 000000000000..e35c67d7cb3d --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ClassDeserializer.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.util.HashMap; + +/** + * Deserializing a JDK 1.2 Class. + */ +public class ClassDeserializer extends AbstractMapDeserializer { + private static final HashMap _primClasses + = new HashMap(); + + private ClassLoader _loader; + + public ClassDeserializer(ClassLoader loader) + { + _loader = loader; + } + + public Class getType() + { + return Class.class; + } + + public Object readMap(AbstractHessianInput in) + throws IOException + { + int ref = in.addRef(null); + + String name = null; + + while (! in.isEnd()) { + String key = in.readString(); + + if (key.equals("name")) + name = in.readString(); + else + in.readObject(); + } + + in.readMapEnd(); + + Object value = create(name); + + in.setRef(ref, value); + + return value; + } + + public Object readObject(AbstractHessianInput in, String []fieldNames) + throws IOException + { + int ref = in.addRef(null); + + String name = null; + + for (int i = 0; i < fieldNames.length; i++) { + if ("name".equals(fieldNames[i])) + name = in.readString(); + else + in.readObject(); + } + + Object value = create(name); + + in.setRef(ref, value); + + return value; + } + + Object create(String name) + throws IOException + { + if (name == null) + throw new IOException("Serialized Class expects name."); + + Class cl = _primClasses.get(name); + + if (cl != null) + return cl; + + try { + if (_loader != null) + return Class.forName(name, false, _loader); + else + return Class.forName(name); + } catch (Exception e) { + throw new IOExceptionWrapper(e); + } + } + + static { + _primClasses.put("void", void.class); + _primClasses.put("boolean", boolean.class); + _primClasses.put("java.lang.Boolean", Boolean.class); + _primClasses.put("byte", byte.class); + _primClasses.put("java.lang.Byte", Byte.class); + _primClasses.put("char", char.class); + _primClasses.put("java.lang.Character", Character.class); + _primClasses.put("short", short.class); + _primClasses.put("java.lang.Short", Short.class); + _primClasses.put("int", int.class); + _primClasses.put("java.lang.Integer", Integer.class); + _primClasses.put("long", long.class); + _primClasses.put("java.lang.Long", Long.class); + _primClasses.put("float", float.class); + _primClasses.put("java.lang.Float", Float.class); + _primClasses.put("double", double.class); + _primClasses.put("java.lang.Double", Double.class); + _primClasses.put("java.lang.String", String.class); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ClassSerializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ClassSerializer.java new file mode 100644 index 000000000000..5d7d6233cb16 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ClassSerializer.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; + +/** + * Serializing a remote object. + */ +public class ClassSerializer extends AbstractSerializer { + public void writeObject(Object obj, AbstractHessianOutput out) + throws IOException + { + Class cl = (Class) obj; + + if (cl == null) { + out.writeNull(); + } + else if (out.addRef(obj)) { + return; + } + else { + int ref = out.writeObjectBegin("java.lang.Class"); + + if (ref < -1) { + out.writeString("name"); + out.writeString(cl.getName()); + out.writeMapEnd(); + } + else { + if (ref == -1) { + out.writeInt(1); + out.writeString("name"); + out.writeObjectBegin("java.lang.Class"); + } + + out.writeString(cl.getName()); + } + } + } +} 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 new file mode 100644 index 000000000000..c71312061129 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/CollectionDeserializer.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.util.*; + +/** + * Deserializing a JDK 1.2 Collection. + */ +public class CollectionDeserializer extends AbstractListDeserializer { + private Class _type; + + public CollectionDeserializer(Class type) + { + _type = type; + } + + public Class getType() + { + return _type; + } + + public Object readList(AbstractHessianInput in, int length) + throws IOException + { + Collection list = createList(); + + in.addRef(list); + + while (! in.isEnd()) + list.add(in.readObject()); + + in.readEnd(); + + return list; + } + + public Object readLengthList(AbstractHessianInput in, int length) + throws IOException + { + Collection list = createList(); + + in.addRef(list); + + for (; length > 0; length--) + list.add(in.readObject()); + + return list; + } + + private Collection createList() + throws IOException + { + Collection list = null; + + if (_type == null) + list = new ArrayList(); + else if (! _type.isInterface()) { + try { + list = (Collection) _type.newInstance(); + } catch (Exception e) { + } + } + + if (list != null) { + } + else if (SortedSet.class.isAssignableFrom(_type)) + list = new TreeSet(); + else if (Set.class.isAssignableFrom(_type)) + list = new HashSet(); + else if (List.class.isAssignableFrom(_type)) + list = new ArrayList(); + else if (Collection.class.isAssignableFrom(_type)) + list = new ArrayList(); + else { + try { + list = (Collection) _type.newInstance(); + } catch (Exception e) { + throw new IOExceptionWrapper(e); + } + } + + return list; + } +} + + diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/CollectionSerializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/CollectionSerializer.java new file mode 100644 index 000000000000..135acbf05a8b --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/CollectionSerializer.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; + +/** + * Serializing a JDK 1.2 Collection. + */ +public class CollectionSerializer extends AbstractSerializer +{ + private boolean _sendJavaType = true; + + /** + * Set true if the java type of the collection should be sent. + */ + public void setSendJavaType(boolean sendJavaType) + { + _sendJavaType = sendJavaType; + } + + /** + * Return true if the java type of the collection should be sent. + */ + public boolean getSendJavaType() + { + return _sendJavaType; + } + + public void writeObject(Object obj, AbstractHessianOutput out) + throws IOException + { + if (out.addRef(obj)) + return; + + Collection list = (Collection) obj; + + Class cl = obj.getClass(); + boolean hasEnd; + + if (cl.equals(ArrayList.class) + || ! _sendJavaType + || ! Serializable.class.isAssignableFrom(cl)) + hasEnd = out.writeListBegin(list.size(), null); + else + hasEnd = out.writeListBegin(list.size(), obj.getClass().getName()); + + Iterator iter = list.iterator(); + while (iter.hasNext()) { + Object value = iter.next(); + + out.writeObject(value); + } + + if (hasEnd) + out.writeListEnd(); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Deflation.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Deflation.java new file mode 100644 index 000000000000..68cd46ec3bf7 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Deflation.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.util.*; +import java.util.zip.*; + +import java.io.*; + +import com.alibaba.com.caucho.hessian.io.*; + +public class Deflation extends HessianEnvelope { + public Deflation() + { + } + + public Hessian2Output wrap(Hessian2Output out) + throws IOException + { + OutputStream os = new DeflateOutputStream(out); + + Hessian2Output filterOut = new Hessian2Output(os); + + filterOut.setCloseStreamOnClose(true); + + return filterOut; + } + + public Hessian2Input unwrap(Hessian2Input in) + throws IOException + { + int version = in.readEnvelope(); + + String method = in.readMethod(); + + if (! method.equals(getClass().getName())) + throw new IOException("expected hessian Envelope method '" + + getClass().getName() + "' at '" + method + "'"); + + return unwrapHeaders(in); + } + + public Hessian2Input unwrapHeaders(Hessian2Input in) + throws IOException + { + InputStream is = new DeflateInputStream(in); + + Hessian2Input filter = new Hessian2Input(is); + + filter.setCloseStreamOnClose(true); + + return filter; + } + + static class DeflateOutputStream extends OutputStream { + private Hessian2Output _out; + private OutputStream _bodyOut; + private DeflaterOutputStream _deflateOut; + + DeflateOutputStream(Hessian2Output out) + throws IOException + { + _out = out; + + _out.startEnvelope(Deflation.class.getName()); + + _out.writeInt(0); + + _bodyOut = _out.getBytesOutputStream(); + + _deflateOut = new DeflaterOutputStream(_bodyOut); + } + + public void write(int ch) + throws IOException + { + _deflateOut.write(ch); + } + + public void write(byte []buffer, int offset, int length) + throws IOException + { + _deflateOut.write(buffer, offset, length); + } + + public void close() + throws IOException + { + Hessian2Output out = _out; + _out = null; + + if (out != null) { + _deflateOut.close(); + _bodyOut.close(); + + out.writeInt(0); + + out.completeEnvelope(); + + out.close(); + } + } + } + + static class DeflateInputStream extends InputStream { + private Hessian2Input _in; + + private InputStream _bodyIn; + private InflaterInputStream _inflateIn; + + DeflateInputStream(Hessian2Input in) + throws IOException + { + _in = in; + + int len = in.readInt(); + + if (len != 0) + throw new IOException("expected no headers"); + + _bodyIn = _in.readInputStream(); + + _inflateIn = new InflaterInputStream(_bodyIn); + } + + public int read() + throws IOException + { + return _inflateIn.read(); + } + + public int read(byte []buffer, int offset, int length) + throws IOException + { + return _inflateIn.read(buffer, offset, length); + } + + public void close() + throws IOException + { + Hessian2Input in = _in; + _in = null; + + if (in != null) { + _inflateIn.close(); + _bodyIn.close(); + + int len = in.readInt(); + + if (len != 0) + throw new IOException("Unexpected footer"); + + in.completeEnvelope(); + + in.close(); + } + } + } +} 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 new file mode 100644 index 000000000000..5f8cb814b74e --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Deserializer.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; + +/** + * Deserializing an object. + */ +public interface Deserializer { + public Class getType(); + + public Object readObject(AbstractHessianInput in) + throws IOException; + + public Object readList(AbstractHessianInput in, int length) + throws IOException; + + public Object readLengthList(AbstractHessianInput in, int length) + throws IOException; + + public Object readMap(AbstractHessianInput in) + 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/EnumDeserializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/EnumDeserializer.java new file mode 100644 index 000000000000..fab492747c5b --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/EnumDeserializer.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.lang.reflect.Method; + +/** + * Deserializing an enum valued object + */ +public class EnumDeserializer extends AbstractDeserializer { + private Class _enumType; + private Method _valueOf; + + public EnumDeserializer(Class cl) + { + // hessian/33b[34], hessian/3bb[78] + if (cl.isEnum()) + _enumType = cl; + else if (cl.getSuperclass().isEnum()) + _enumType = cl.getSuperclass(); + else + throw new RuntimeException("Class " + cl.getName() + " is not an enum"); + + try { + _valueOf = _enumType.getMethod("valueOf", + new Class[] { Class.class, String.class }); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public Class getType() + { + return _enumType; + } + + public Object readMap(AbstractHessianInput in) + throws IOException + { + String name = null; + + while (! in.isEnd()) { + String key = in.readString(); + + if (key.equals("name")) + name = in.readString(); + else + in.readObject(); + } + + in.readMapEnd(); + + Object obj = create(name); + + in.addRef(obj); + + return obj; + } + + public Object readObject(AbstractHessianInput in, String []fieldNames) + throws IOException + { + String name = null; + + for (int i = 0; i < fieldNames.length; i++) { + if ("name".equals(fieldNames[i])) + name = in.readString(); + else + in.readObject(); + } + + Object obj = create(name); + + in.addRef(obj); + + return obj; + } + + private Object create(String name) + throws IOException + { + if (name == null) + throw new IOException(_enumType.getName() + " expects name."); + + try { + return _valueOf.invoke(null, _enumType, name); + } catch (Exception e) { + throw new IOExceptionWrapper(e); + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/EnumSerializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/EnumSerializer.java new file mode 100644 index 000000000000..cfb0ee97420d --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/EnumSerializer.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.lang.reflect.Method; + +/** + * Serializing an object for known object types. + */ +public class EnumSerializer extends AbstractSerializer { + private Method _name; + + public EnumSerializer(Class cl) + { + // hessian/32b[12], hessian/3ab[23] + if (! cl.isEnum() && cl.getSuperclass().isEnum()) + cl = cl.getSuperclass(); + + try { + _name = cl.getMethod("name", new Class[0]); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public void writeObject(Object obj, AbstractHessianOutput out) + throws IOException + { + if (out.addRef(obj)) + return; + + Class cl = obj.getClass(); + + if (! cl.isEnum() && cl.getSuperclass().isEnum()) + cl = cl.getSuperclass(); + + String name = null; + try { + name = (String) _name.invoke(obj, (Object[]) null); + } catch (Exception e) { + throw new RuntimeException(e); + } + + int ref = out.writeObjectBegin(cl.getName()); + + if (ref < -1) { + out.writeString("name"); + out.writeString(name); + out.writeMapEnd(); + } + else { + if (ref == -1) { + out.writeClassFieldLength(1); + out.writeString("name"); + out.writeObjectBegin(cl.getName()); + } + + out.writeString(name); + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/EnumerationDeserializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/EnumerationDeserializer.java new file mode 100644 index 000000000000..412fe758e892 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/EnumerationDeserializer.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.util.Vector; + +/** + * Deserializing a JDK 1.2 Collection. + */ +public class EnumerationDeserializer extends AbstractListDeserializer { + private static EnumerationDeserializer _deserializer; + + public static EnumerationDeserializer create() + { + if (_deserializer == null) + _deserializer = new EnumerationDeserializer(); + + return _deserializer; + } + + public Object readList(AbstractHessianInput in, int length) + throws IOException + { + Vector list = new Vector(); + + in.addRef(list); + + while (! in.isEnd()) + list.add(in.readObject()); + + in.readEnd(); + + return list.elements(); + } +} + + diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/EnumerationSerializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/EnumerationSerializer.java new file mode 100644 index 000000000000..be116eb18c80 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/EnumerationSerializer.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.util.Enumeration; + +/** + * Serializing a JDK 1.2 Enumeration. + */ +public class EnumerationSerializer extends AbstractSerializer { + private static EnumerationSerializer _serializer; + + public static EnumerationSerializer create() + { + if (_serializer == null) + _serializer = new EnumerationSerializer(); + + return _serializer; + } + + public void writeObject(Object obj, AbstractHessianOutput out) + throws IOException + { + Enumeration iter = (Enumeration) obj; + + boolean hasEnd = out.writeListBegin(-1, null); + + while (iter.hasMoreElements()) { + Object value = iter.nextElement(); + + out.writeObject(value); + } + + if (hasEnd) + out.writeListEnd(); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/EnvelopeFactory.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/EnvelopeFactory.java new file mode 100644 index 000000000000..078c3edb50bb --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/EnvelopeFactory.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.util.logging.*; + +public class EnvelopeFactory +{ + private static final Logger log + = Logger.getLogger(EnvelopeFactory.class.getName()); +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ExtSerializerFactory.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ExtSerializerFactory.java new file mode 100644 index 000000000000..e19b8c935ad5 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ExtSerializerFactory.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.util.HashMap; + +/** + * Factory for returning serialization methods. + */ +public class ExtSerializerFactory extends AbstractSerializerFactory { + private HashMap _serializerMap = new HashMap(); + private HashMap _deserializerMap = new HashMap(); + + /** + * Adds a serializer. + * + * @param cl the class of the serializer + * @param serializer the serializer + */ + public void addSerializer(Class cl, Serializer serializer) + { + _serializerMap.put(cl, serializer); + } + + /** + * Adds a deserializer. + * + * @param cl the class of the deserializer + * @param deserializer the deserializer + */ + public void addDeserializer(Class cl, Deserializer deserializer) + { + _deserializerMap.put(cl, deserializer); + } + + /** + * Returns the serializer for a class. + * + * @param cl the class of the object that needs to be serialized. + * + * @return a serializer object for the serialization. + */ + public Serializer getSerializer(Class cl) + throws HessianProtocolException + { + return (Serializer) _serializerMap.get(cl); + } + + /** + * Returns the deserializer for a class. + * + * @param cl the class of the object that needs to be deserialized. + * + * @return a deserializer object for the serialization. + */ + public Deserializer getDeserializer(Class cl) + throws HessianProtocolException + { + return (Deserializer) _deserializerMap.get(cl); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2Constants.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2Constants.java new file mode 100644 index 000000000000..ebe93d8b6b2b --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2Constants.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +public interface Hessian2Constants +{ + public static final int BC_BINARY = 'B'; // final chunk + public static final int BC_BINARY_CHUNK = 'A'; // non-final chunk + public static final int BC_BINARY_DIRECT = 0x20; // 1-byte length binary + public static final int BINARY_DIRECT_MAX = 0x0f; + public static final int BC_BINARY_SHORT = 0x34; // 2-byte length binary + public static final int BINARY_SHORT_MAX = 0x3ff; // 0-1023 binary + + public static final int BC_CLASS_DEF = 'C'; // object/class definition + + public static final int BC_DATE = 0x4a; // 64-bit millisecond UTC date + public static final int BC_DATE_MINUTE = 0x4b; // 32-bit minute UTC date + + public static final int BC_DOUBLE = 'D'; // IEEE 64-bit double + + public static final int BC_DOUBLE_ZERO = 0x5b; + public static final int BC_DOUBLE_ONE = 0x5c; + public static final int BC_DOUBLE_BYTE = 0x5d; + public static final int BC_DOUBLE_SHORT = 0x5e; + public static final int BC_DOUBLE_MILL = 0x5f; + + public static final int BC_FALSE = 'F'; // boolean false + + public static final int BC_INT = 'I'; // 32-bit int + + public static final int INT_DIRECT_MIN = -0x10; + public static final int INT_DIRECT_MAX = 0x2f; + public static final int BC_INT_ZERO = 0x90; + + public static final int INT_BYTE_MIN = -0x800; + public static final int INT_BYTE_MAX = 0x7ff; + public static final int BC_INT_BYTE_ZERO = 0xc8; + + public static final int BC_END = 'Z'; + + public static final int INT_SHORT_MIN = -0x40000; + public static final int INT_SHORT_MAX = 0x3ffff; + public static final int BC_INT_SHORT_ZERO = 0xd4; + + public static final int BC_LIST_VARIABLE =0x55; + public static final int BC_LIST_FIXED = 'V'; + public static final int BC_LIST_VARIABLE_UNTYPED = 0x57; + public static final int BC_LIST_FIXED_UNTYPED =0x58; + + public static final int BC_LIST_DIRECT = 0x70; + public static final int BC_LIST_DIRECT_UNTYPED = 0x78; + public static final int LIST_DIRECT_MAX = 0x7; + + public static final int BC_LONG = 'L'; // 64-bit signed integer + public static final long LONG_DIRECT_MIN = -0x08; + public static final long LONG_DIRECT_MAX = 0x0f; + public static final int BC_LONG_ZERO = 0xe0; + + public static final long LONG_BYTE_MIN = -0x800; + public static final long LONG_BYTE_MAX = 0x7ff; + public static final int BC_LONG_BYTE_ZERO = 0xf8; + + public static final int LONG_SHORT_MIN = -0x40000; + public static final int LONG_SHORT_MAX = 0x3ffff; + public static final int BC_LONG_SHORT_ZERO = 0x3c; + + public static final int BC_LONG_INT = 0x59; + + public static final int BC_MAP = 'M'; + public static final int BC_MAP_UNTYPED = 'H'; + + public static final int BC_NULL = 'N'; + + public static final int BC_OBJECT = 'O'; + public static final int BC_OBJECT_DEF = 'C'; + + public static final int BC_OBJECT_DIRECT = 0x60; + public static final int OBJECT_DIRECT_MAX = 0x0f; + + public static final int BC_REF = 0x51; + + public static final int BC_STRING = 'S'; // final string + public static final int BC_STRING_CHUNK = 'R'; // non-final string + + public static final int BC_STRING_DIRECT = 0x00; + public static final int STRING_DIRECT_MAX = 0x1f; + public static final int BC_STRING_SHORT = 0x30; + public static final int STRING_SHORT_MAX = 0x3ff; + + public static final int BC_TRUE = 'T'; + + public static final int P_PACKET_CHUNK = 0x4f; + public static final int P_PACKET = 'P'; + + public static final int P_PACKET_DIRECT = 0x80; + public static final int PACKET_DIRECT_MAX = 0x7f; + + public static final int P_PACKET_SHORT = 0x70; + public static final int PACKET_SHORT_MAX = 0xfff; +} 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 new file mode 100644 index 000000000000..92d0ba01ed17 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2Input.java @@ -0,0 +1,2798 @@ +/* + * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.*; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.logging.*; + +/** + * Input stream for Hessian requests. + * + *

HessianInput is unbuffered, so any client needs to provide + * its own buffering. + * + *

+ * InputStream is = ...; // from http connection
+ * HessianInput in = new HessianInput(is);
+ * String value;
+ *
+ * in.startReply();         // read reply header
+ * value = in.readString(); // read string value
+ * in.completeReply();      // read reply footer
+ * 
+ */ +public class Hessian2Input + extends AbstractHessianInput + implements Hessian2Constants +{ + private static final Logger log + = Logger.getLogger(Hessian2Input.class.getName()); + + private static final double D_256 = 1.0 / 256.0; + private static final int END_OF_DATA = -2; + + private static Field _detailMessageField; + + private static final int SIZE = 256; + private static final int GAP = 16; + + // factory for deserializing objects in the input stream + protected SerializerFactory _serializerFactory; + + private static boolean _isCloseStreamOnClose; + + protected ArrayList _refs; + protected ArrayList _classDefs; + protected ArrayList _types; + + // the underlying input stream + private InputStream _is; + private final byte []_buffer = new byte[SIZE]; + + // a peek character + private int _offset; + private int _length; + + // true for streaming data + private boolean _isStreaming; + + // the method for a call + private String _method; + private int _argLength; + + private Reader _chunkReader; + private InputStream _chunkInputStream; + + private Throwable _replyFault; + + private StringBuffer _sbuf = new StringBuffer(); + + // true if this is the last chunk + private boolean _isLastChunk; + // the chunk length + private int _chunkLength; + + /** + * Creates a new Hessian input stream, initialized with an + * underlying input stream. + * + * @param is the underlying input stream. + */ + public Hessian2Input(InputStream is) + { + _is = is; + } + + /** + * Sets the serializer factory. + */ + public void setSerializerFactory(SerializerFactory factory) + { + _serializerFactory = factory; + } + + /** + * Gets the serializer factory. + */ + public SerializerFactory getSerializerFactory() + { + return _serializerFactory; + } + + /** + * Gets the serializer factory, creating a default if necessary. + */ + public final SerializerFactory findSerializerFactory() + { + SerializerFactory factory = _serializerFactory; + + if (factory == null) + _serializerFactory = factory = new SerializerFactory(); + + return factory; + } + + public void setCloseStreamOnClose(boolean isClose) + { + _isCloseStreamOnClose = isClose; + } + + public boolean isCloseStreamOnClose() + { + return _isCloseStreamOnClose; + } + + /** + * Returns the calls method + */ + public String getMethod() + { + return _method; + } + + /** + * Returns any reply fault. + */ + public Throwable getReplyFault() + { + return _replyFault; + } + + /** + * Starts reading the call + * + *
+   * c major minor
+   * 
+ */ + public int readCall() + throws IOException + { + int tag = read(); + + if (tag != 'C') + throw error("expected hessian call ('C') at " + codeName(tag)); + + return 0; + } + + /** + * Starts reading the envelope + * + *
+   * E major minor
+   * 
+ */ + public int readEnvelope() + throws IOException + { + int tag = read(); + int version = 0; + + if (tag == 'H') { + int major = read(); + int minor = read(); + + version = (major << 16) + minor; + + tag = read(); + } + + if (tag != 'E') + throw error("expected hessian Envelope ('E') at " + codeName(tag)); + + return version; + } + + /** + * Completes reading the envelope + * + *

A successful completion will have a single value: + * + *

+   * Z
+   * 
+ */ + public void completeEnvelope() + throws IOException + { + int tag = read(); + + if (tag != 'Z') + error("expected end of envelope at " + codeName(tag)); + } + + /** + * Starts reading the call + * + *

A successful completion will have a single value: + * + *

+   * string
+   * 
+ */ + public String readMethod() + throws IOException + { + _method = readString(); + + return _method; + } + + /** + * Returns the number of method arguments + * + *
+   * int
+   * 
+ */ + @Override + public int readMethodArgLength() + throws IOException + { + return readInt(); + } + + /** + * Starts reading the call, including the headers. + * + *

The call expects the following protocol data + * + *

+   * c major minor
+   * m b16 b8 method
+   * 
+ */ + public void startCall() + throws IOException + { + readCall(); + + readMethod(); + } + + /** + * Completes reading the call + * + *

A successful completion will have a single value: + * + *

+   * 
+ */ + public void completeCall() + throws IOException + { + } + + /** + * Reads a reply as an object. + * If the reply has a fault, throws the exception. + */ + @Override + public Object readReply(Class expectedClass) + throws Throwable + { + int tag = read(); + + if (tag == 'R') + return readObject(expectedClass); + else if (tag == 'F') { + HashMap map = (HashMap) readObject(HashMap.class); + + throw prepareFault(map); + } + else { + StringBuilder sb = new StringBuilder(); + sb.append((char) tag); + + try { + int ch; + + while ((ch = read()) >= 0) { + sb.append((char) ch); + } + } catch (IOException e) { + log.log(Level.FINE, e.toString(), e); + } + + throw error("expected hessian reply at " + codeName(tag) + "\n" + + sb); + } + } + + /** + * Starts reading the reply + * + *

A successful completion will have a single value: + * + *

+   * r
+   * 
+ */ + public void startReply() + throws Throwable + { + // XXX: for variable length (?) + + readReply(Object.class); + } + + /** + * Prepares the fault. + */ + private Throwable prepareFault(HashMap fault) + throws IOException + { + Object detail = fault.get("detail"); + String message = (String) fault.get("message"); + + if (detail instanceof Throwable) { + _replyFault = (Throwable) detail; + + if (message != null && _detailMessageField != null) { + try { + _detailMessageField.set(_replyFault, message); + } catch (Throwable e) { + } + } + + return _replyFault; + } + + else { + String code = (String) fault.get("code"); + + _replyFault = new HessianServiceException(message, code, detail); + + return _replyFault; + } + } + + /** + * Completes reading the call + * + *

A successful completion will have a single value: + * + *

+   * z
+   * 
+ */ + public void completeReply() + throws IOException + { + } + + /** + * Completes reading the call + * + *

A successful completion will have a single value: + * + *

+   * z
+   * 
+ */ + public void completeValueReply() + throws IOException + { + int tag = read(); + + if (tag != 'Z') + error("expected end of reply at " + codeName(tag)); + } + + /** + * Reads a header, returning null if there are no headers. + * + *
+   * H b16 b8 value
+   * 
+ */ + public String readHeader() + throws IOException + { + return null; + } + + /** + * Starts reading the message + * + *
+   * p major minor
+   * 
+ */ + public int startMessage() + throws IOException + { + int tag = read(); + + if (tag == 'p') + _isStreaming = false; + else if (tag == 'P') + _isStreaming = true; + else + throw error("expected Hessian message ('p') at " + codeName(tag)); + + int major = read(); + int minor = read(); + + return (major << 16) + minor; + } + + /** + * Completes reading the message + * + *

A successful completion will have a single value: + * + *

+   * z
+   * 
+ */ + public void completeMessage() + throws IOException + { + int tag = read(); + + if (tag != 'Z') + error("expected end of message at " + codeName(tag)); + } + + /** + * Reads a null + * + *
+   * N
+   * 
+ */ + public void readNull() + throws IOException + { + int tag = read(); + + switch (tag) { + case 'N': return; + + default: + throw expect("null", tag); + } + } + + /** + * Reads a boolean + * + *
+   * T
+   * F
+   * 
+ */ + public boolean readBoolean() + throws IOException + { + int tag = _offset < _length ? (_buffer[_offset++] & 0xff) : read(); + + switch (tag) { + case 'T': return true; + case 'F': return false; + + // direct integer + case 0x80: case 0x81: case 0x82: case 0x83: + case 0x84: case 0x85: case 0x86: case 0x87: + case 0x88: case 0x89: case 0x8a: case 0x8b: + case 0x8c: case 0x8d: case 0x8e: case 0x8f: + + case 0x90: case 0x91: case 0x92: case 0x93: + case 0x94: case 0x95: case 0x96: case 0x97: + case 0x98: case 0x99: case 0x9a: case 0x9b: + case 0x9c: case 0x9d: case 0x9e: case 0x9f: + + case 0xa0: case 0xa1: case 0xa2: case 0xa3: + case 0xa4: case 0xa5: case 0xa6: case 0xa7: + case 0xa8: case 0xa9: case 0xaa: case 0xab: + case 0xac: case 0xad: case 0xae: case 0xaf: + + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb4: case 0xb5: case 0xb6: case 0xb7: + case 0xb8: case 0xb9: case 0xba: case 0xbb: + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + return tag != BC_INT_ZERO; + + // INT_BYTE = 0 + case 0xc8: + return read() != 0; + + // INT_BYTE != 0 + case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc4: case 0xc5: case 0xc6: case 0xc7: + case 0xc9: case 0xca: case 0xcb: + case 0xcc: case 0xcd: case 0xce: case 0xcf: + read(); + return true; + + // INT_SHORT = 0 + case 0xd4: + return (256 * read() + read()) != 0; + + // INT_SHORT != 0 + case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xd5: case 0xd6: case 0xd7: + read(); + read(); + return true; + + case 'I': return + parseInt() != 0; + + case 0xd8: case 0xd9: case 0xda: case 0xdb: + case 0xdc: case 0xdd: case 0xde: case 0xdf: + + case 0xe0: case 0xe1: case 0xe2: case 0xe3: + case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe8: case 0xe9: case 0xea: case 0xeb: + case 0xec: case 0xed: case 0xee: case 0xef: + return tag != BC_LONG_ZERO; + + // LONG_BYTE = 0 + case 0xf8: + return read() != 0; + + // LONG_BYTE != 0 + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: + read(); + return true; + + // INT_SHORT = 0 + case 0x3c: + return (256 * read() + read()) != 0; + + // INT_SHORT != 0 + case 0x38: case 0x39: case 0x3a: case 0x3b: + case 0x3d: case 0x3e: case 0x3f: + read(); + read(); + return true; + + case BC_LONG_INT: + return (0x1000000L * read() + + 0x10000L * read() + + 0x100 * read() + + read()) != 0; + + case 'L': + return parseLong() != 0; + + case BC_DOUBLE_ZERO: + return false; + + case BC_DOUBLE_ONE: + return true; + + case BC_DOUBLE_BYTE: + return read() != 0; + + case BC_DOUBLE_SHORT: + return (0x100 * read() + read()) != 0; + + case BC_DOUBLE_MILL: + { + int mills = parseInt(); + + return mills != 0; + } + + case 'D': + return parseDouble() != 0.0; + + case 'N': + return false; + + default: + throw expect("boolean", tag); + } + } + + /** + * Reads a short + * + *
+   * I b32 b24 b16 b8
+   * 
+ */ + public short readShort() + throws IOException + { + return (short) readInt(); + } + + /** + * Reads an integer + * + *
+   * I b32 b24 b16 b8
+   * 
+ */ + public final int readInt() + throws IOException + { + //int tag = _offset < _length ? (_buffer[_offset++] & 0xff) : read(); + int tag = read(); + + switch (tag) { + case 'N': + return 0; + + case 'F': + return 0; + + case 'T': + return 1; + + // direct integer + case 0x80: case 0x81: case 0x82: case 0x83: + case 0x84: case 0x85: case 0x86: case 0x87: + case 0x88: case 0x89: case 0x8a: case 0x8b: + case 0x8c: case 0x8d: case 0x8e: case 0x8f: + + case 0x90: case 0x91: case 0x92: case 0x93: + case 0x94: case 0x95: case 0x96: case 0x97: + case 0x98: case 0x99: case 0x9a: case 0x9b: + case 0x9c: case 0x9d: case 0x9e: case 0x9f: + + case 0xa0: case 0xa1: case 0xa2: case 0xa3: + case 0xa4: case 0xa5: case 0xa6: case 0xa7: + case 0xa8: case 0xa9: case 0xaa: case 0xab: + case 0xac: case 0xad: case 0xae: case 0xaf: + + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb4: case 0xb5: case 0xb6: case 0xb7: + case 0xb8: case 0xb9: case 0xba: case 0xbb: + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + return tag - BC_INT_ZERO; + + /* byte int */ + case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc4: case 0xc5: case 0xc6: case 0xc7: + case 0xc8: case 0xc9: case 0xca: case 0xcb: + case 0xcc: case 0xcd: case 0xce: case 0xcf: + return ((tag - BC_INT_BYTE_ZERO) << 8) + read(); + + /* short int */ + case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xd4: case 0xd5: case 0xd6: case 0xd7: + return ((tag - BC_INT_SHORT_ZERO) << 16) + 256 * read() + read(); + + case 'I': + case BC_LONG_INT: + return ((read() << 24) + + (read() << 16) + + (read() << 8) + + read()); + + // direct long + case 0xd8: case 0xd9: case 0xda: case 0xdb: + case 0xdc: case 0xdd: case 0xde: case 0xdf: + + case 0xe0: case 0xe1: case 0xe2: case 0xe3: + case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe8: case 0xe9: case 0xea: case 0xeb: + case 0xec: case 0xed: case 0xee: case 0xef: + return tag - BC_LONG_ZERO; + + /* byte long */ + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: + return ((tag - BC_LONG_BYTE_ZERO) << 8) + read(); + + /* short long */ + case 0x38: case 0x39: case 0x3a: case 0x3b: + case 0x3c: case 0x3d: case 0x3e: case 0x3f: + return ((tag - BC_LONG_SHORT_ZERO) << 16) + 256 * read() + read(); + + case 'L': + return (int) parseLong(); + + case BC_DOUBLE_ZERO: + return 0; + + case BC_DOUBLE_ONE: + return 1; + + //case LONG_BYTE: + case BC_DOUBLE_BYTE: + return (byte) (_offset < _length ? _buffer[_offset++] : read()); + + //case INT_SHORT: + //case LONG_SHORT: + case BC_DOUBLE_SHORT: + return (short) (256 * read() + read()); + + case BC_DOUBLE_MILL: + { + int mills = parseInt(); + + return (int) (0.001 * mills); + } + + case 'D': + return (int) parseDouble(); + + default: + throw expect("integer", tag); + } + } + + /** + * Reads a long + * + *
+   * L b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ */ + public long readLong() + throws IOException + { + int tag = read(); + + switch (tag) { + case 'N': + return 0; + + case 'F': + return 0; + + case 'T': + return 1; + + // direct integer + case 0x80: case 0x81: case 0x82: case 0x83: + case 0x84: case 0x85: case 0x86: case 0x87: + case 0x88: case 0x89: case 0x8a: case 0x8b: + case 0x8c: case 0x8d: case 0x8e: case 0x8f: + + case 0x90: case 0x91: case 0x92: case 0x93: + case 0x94: case 0x95: case 0x96: case 0x97: + case 0x98: case 0x99: case 0x9a: case 0x9b: + case 0x9c: case 0x9d: case 0x9e: case 0x9f: + + case 0xa0: case 0xa1: case 0xa2: case 0xa3: + case 0xa4: case 0xa5: case 0xa6: case 0xa7: + case 0xa8: case 0xa9: case 0xaa: case 0xab: + case 0xac: case 0xad: case 0xae: case 0xaf: + + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb4: case 0xb5: case 0xb6: case 0xb7: + case 0xb8: case 0xb9: case 0xba: case 0xbb: + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + return tag - BC_INT_ZERO; + + /* byte int */ + case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc4: case 0xc5: case 0xc6: case 0xc7: + case 0xc8: case 0xc9: case 0xca: case 0xcb: + case 0xcc: case 0xcd: case 0xce: case 0xcf: + return ((tag - BC_INT_BYTE_ZERO) << 8) + read(); + + /* short int */ + case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xd4: case 0xd5: case 0xd6: case 0xd7: + return ((tag - BC_INT_SHORT_ZERO) << 16) + 256 * read() + read(); + + //case LONG_BYTE: + case BC_DOUBLE_BYTE: + return (byte) (_offset < _length ? _buffer[_offset++] : read()); + + //case INT_SHORT: + //case LONG_SHORT: + case BC_DOUBLE_SHORT: + return (short) (256 * read() + read()); + + case 'I': + case BC_LONG_INT: + return parseInt(); + + // direct long + case 0xd8: case 0xd9: case 0xda: case 0xdb: + case 0xdc: case 0xdd: case 0xde: case 0xdf: + + case 0xe0: case 0xe1: case 0xe2: case 0xe3: + case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe8: case 0xe9: case 0xea: case 0xeb: + case 0xec: case 0xed: case 0xee: case 0xef: + return tag - BC_LONG_ZERO; + + /* byte long */ + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: + return ((tag - BC_LONG_BYTE_ZERO) << 8) + read(); + + /* short long */ + case 0x38: case 0x39: case 0x3a: case 0x3b: + case 0x3c: case 0x3d: case 0x3e: case 0x3f: + return ((tag - BC_LONG_SHORT_ZERO) << 16) + 256 * read() + read(); + + case 'L': + return parseLong(); + + case BC_DOUBLE_ZERO: + return 0; + + case BC_DOUBLE_ONE: + return 1; + + case BC_DOUBLE_MILL: + { + int mills = parseInt(); + + return (long) (0.001 * mills); + } + + case 'D': + return (long) parseDouble(); + + default: + throw expect("long", tag); + } + } + + /** + * Reads a float + * + *
+   * D b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ */ + public float readFloat() + throws IOException + { + return (float) readDouble(); + } + + /** + * Reads a double + * + *
+   * D b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ */ + public double readDouble() + throws IOException + { + int tag = read(); + + switch (tag) { + case 'N': + return 0; + + case 'F': + return 0; + + case 'T': + return 1; + + // direct integer + case 0x80: case 0x81: case 0x82: case 0x83: + case 0x84: case 0x85: case 0x86: case 0x87: + case 0x88: case 0x89: case 0x8a: case 0x8b: + case 0x8c: case 0x8d: case 0x8e: case 0x8f: + + case 0x90: case 0x91: case 0x92: case 0x93: + case 0x94: case 0x95: case 0x96: case 0x97: + case 0x98: case 0x99: case 0x9a: case 0x9b: + case 0x9c: case 0x9d: case 0x9e: case 0x9f: + + case 0xa0: case 0xa1: case 0xa2: case 0xa3: + case 0xa4: case 0xa5: case 0xa6: case 0xa7: + case 0xa8: case 0xa9: case 0xaa: case 0xab: + case 0xac: case 0xad: case 0xae: case 0xaf: + + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb4: case 0xb5: case 0xb6: case 0xb7: + case 0xb8: case 0xb9: case 0xba: case 0xbb: + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + return tag - 0x90; + + /* byte int */ + case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc4: case 0xc5: case 0xc6: case 0xc7: + case 0xc8: case 0xc9: case 0xca: case 0xcb: + case 0xcc: case 0xcd: case 0xce: case 0xcf: + return ((tag - BC_INT_BYTE_ZERO) << 8) + read(); + + /* short int */ + case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xd4: case 0xd5: case 0xd6: case 0xd7: + return ((tag - BC_INT_SHORT_ZERO) << 16) + 256 * read() + read(); + + case 'I': + case BC_LONG_INT: + return parseInt(); + + // direct long + case 0xd8: case 0xd9: case 0xda: case 0xdb: + case 0xdc: case 0xdd: case 0xde: case 0xdf: + + case 0xe0: case 0xe1: case 0xe2: case 0xe3: + case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe8: case 0xe9: case 0xea: case 0xeb: + case 0xec: case 0xed: case 0xee: case 0xef: + return tag - BC_LONG_ZERO; + + /* byte long */ + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: + return ((tag - BC_LONG_BYTE_ZERO) << 8) + read(); + + /* short long */ + case 0x38: case 0x39: case 0x3a: case 0x3b: + case 0x3c: case 0x3d: case 0x3e: case 0x3f: + return ((tag - BC_LONG_SHORT_ZERO) << 16) + 256 * read() + read(); + + case 'L': + return (double) parseLong(); + + case BC_DOUBLE_ZERO: + return 0; + + case BC_DOUBLE_ONE: + return 1; + + case BC_DOUBLE_BYTE: + return (byte) (_offset < _length ? _buffer[_offset++] : read()); + + case BC_DOUBLE_SHORT: + return (short) (256 * read() + read()); + + case BC_DOUBLE_MILL: + { + int mills = parseInt(); + + return 0.001 * mills; + } + + case 'D': + return parseDouble(); + + default: + throw expect("double", tag); + } + } + + /** + * Reads a date. + * + *
+   * T b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ */ + public long readUTCDate() + throws IOException + { + int tag = read(); + + if (tag == BC_DATE) { + return parseLong(); + } + else if (tag == BC_DATE_MINUTE) { + return parseInt() * 60000L; + } + else + throw expect("date", tag); + } + + /** + * Reads a byte from the stream. + */ + public int readChar() + throws IOException + { + if (_chunkLength > 0) { + _chunkLength--; + if (_chunkLength == 0 && _isLastChunk) + _chunkLength = END_OF_DATA; + + int ch = parseUTF8Char(); + return ch; + } + else if (_chunkLength == END_OF_DATA) { + _chunkLength = 0; + return -1; + } + + int tag = read(); + + switch (tag) { + case 'N': + return -1; + + case 'S': + case BC_STRING_CHUNK: + _isLastChunk = tag == 'S'; + _chunkLength = (read() << 8) + read(); + + _chunkLength--; + int value = parseUTF8Char(); + + // special code so successive read byte won't + // be read as a single object. + if (_chunkLength == 0 && _isLastChunk) + _chunkLength = END_OF_DATA; + + return value; + + default: + throw expect("char", tag); + } + } + + /** + * Reads a byte array from the stream. + */ + public int readString(char []buffer, int offset, int length) + throws IOException + { + int readLength = 0; + + if (_chunkLength == END_OF_DATA) { + _chunkLength = 0; + return -1; + } + else if (_chunkLength == 0) { + int tag = read(); + + switch (tag) { + case 'N': + return -1; + + case 'S': + case BC_STRING_CHUNK: + _isLastChunk = tag == 'S'; + _chunkLength = (read() << 8) + read(); + break; + + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x18: case 0x19: case 0x1a: case 0x1b: + case 0x1c: case 0x1d: case 0x1e: case 0x1f: + _isLastChunk = true; + _chunkLength = tag - 0x00; + break; + + default: + throw expect("string", tag); + } + } + + while (length > 0) { + if (_chunkLength > 0) { + buffer[offset++] = (char) parseUTF8Char(); + _chunkLength--; + length--; + readLength++; + } + else if (_isLastChunk) { + if (readLength == 0) + return -1; + else { + _chunkLength = END_OF_DATA; + return readLength; + } + } + else { + int tag = read(); + + switch (tag) { + case 'S': + case BC_STRING_CHUNK: + _isLastChunk = tag == 'S'; + _chunkLength = (read() << 8) + read(); + break; + + default: + throw expect("string", tag); + } + } + } + + if (readLength == 0) + return -1; + else if (_chunkLength > 0 || ! _isLastChunk) + return readLength; + else { + _chunkLength = END_OF_DATA; + return readLength; + } + } + + /** + * Reads a string + * + *
+   * S b16 b8 string value
+   * 
+ */ + public String readString() + throws IOException + { + int tag = read(); + + switch (tag) { + case 'N': + return null; + case 'T': + return "true"; + case 'F': + return "false"; + + // direct integer + case 0x80: case 0x81: case 0x82: case 0x83: + case 0x84: case 0x85: case 0x86: case 0x87: + case 0x88: case 0x89: case 0x8a: case 0x8b: + case 0x8c: case 0x8d: case 0x8e: case 0x8f: + + case 0x90: case 0x91: case 0x92: case 0x93: + case 0x94: case 0x95: case 0x96: case 0x97: + case 0x98: case 0x99: case 0x9a: case 0x9b: + case 0x9c: case 0x9d: case 0x9e: case 0x9f: + + case 0xa0: case 0xa1: case 0xa2: case 0xa3: + case 0xa4: case 0xa5: case 0xa6: case 0xa7: + case 0xa8: case 0xa9: case 0xaa: case 0xab: + case 0xac: case 0xad: case 0xae: case 0xaf: + + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb4: case 0xb5: case 0xb6: case 0xb7: + case 0xb8: case 0xb9: case 0xba: case 0xbb: + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + return String.valueOf((tag - 0x90)); + + /* byte int */ + case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc4: case 0xc5: case 0xc6: case 0xc7: + case 0xc8: case 0xc9: case 0xca: case 0xcb: + case 0xcc: case 0xcd: case 0xce: case 0xcf: + return String.valueOf(((tag - BC_INT_BYTE_ZERO) << 8) + read()); + + /* short int */ + case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xd4: case 0xd5: case 0xd6: case 0xd7: + return String.valueOf(((tag - BC_INT_SHORT_ZERO) << 16) + + 256 * read() + read()); + + case 'I': + case BC_LONG_INT: + return String.valueOf(parseInt()); + + // direct long + case 0xd8: case 0xd9: case 0xda: case 0xdb: + case 0xdc: case 0xdd: case 0xde: case 0xdf: + + case 0xe0: case 0xe1: case 0xe2: case 0xe3: + case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe8: case 0xe9: case 0xea: case 0xeb: + case 0xec: case 0xed: case 0xee: case 0xef: + return String.valueOf(tag - BC_LONG_ZERO); + + /* byte long */ + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: + return String.valueOf(((tag - BC_LONG_BYTE_ZERO) << 8) + read()); + + /* short long */ + case 0x38: case 0x39: case 0x3a: case 0x3b: + case 0x3c: case 0x3d: case 0x3e: case 0x3f: + return String.valueOf(((tag - BC_LONG_SHORT_ZERO) << 16) + + 256 * read() + read()); + + case 'L': + return String.valueOf(parseLong()); + + case BC_DOUBLE_ZERO: + return "0.0"; + + case BC_DOUBLE_ONE: + return "1.0"; + + case BC_DOUBLE_BYTE: + return String.valueOf((byte) (_offset < _length + ? _buffer[_offset++] + : read())); + + case BC_DOUBLE_SHORT: + return String.valueOf(((short) (256 * read() + read()))); + + case BC_DOUBLE_MILL: + { + int mills = parseInt(); + + return String.valueOf(0.001 * mills); + } + + case 'D': + return String.valueOf(parseDouble()); + + case 'S': + case BC_STRING_CHUNK: + _isLastChunk = tag == 'S'; + _chunkLength = (read() << 8) + read(); + + _sbuf.setLength(0); + int ch; + + while ((ch = parseChar()) >= 0) + _sbuf.append((char) ch); + + return _sbuf.toString(); + + // 0-byte string + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x18: case 0x19: case 0x1a: case 0x1b: + case 0x1c: case 0x1d: case 0x1e: case 0x1f: + _isLastChunk = true; + _chunkLength = tag - 0x00; + + _sbuf.setLength(0); + + while ((ch = parseChar()) >= 0) + _sbuf.append((char) ch); + + return _sbuf.toString(); + + case 0x30: case 0x31: case 0x32: case 0x33: + _isLastChunk = true; + _chunkLength = (tag - 0x30) * 256 + read(); + + _sbuf.setLength(0); + + while ((ch = parseChar()) >= 0) + _sbuf.append((char) ch); + + return _sbuf.toString(); + + default: + throw expect("string", tag); + } + } + + /** + * Reads a byte array + * + *
+   * B b16 b8 data value
+   * 
+ */ + public byte []readBytes() + throws IOException + { + int tag = read(); + + switch (tag) { + case 'N': + return null; + + case 'B': + case BC_BINARY_CHUNK: + _isLastChunk = tag == 'B'; + _chunkLength = (read() << 8) + read(); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + int data; + while ((data = parseByte()) >= 0) + bos.write(data); + + return bos.toByteArray(); + + case 0x20: case 0x21: case 0x22: case 0x23: + case 0x24: case 0x25: case 0x26: case 0x27: + case 0x28: case 0x29: case 0x2a: case 0x2b: + case 0x2c: case 0x2d: case 0x2e: case 0x2f: + { + _isLastChunk = true; + _chunkLength = tag - 0x20; + + byte []buffer = new byte[_chunkLength]; + + int k = 0; + while ((data = parseByte()) >= 0) + buffer[k++] = (byte) data; + + return buffer; + } + + case 0x34: case 0x35: case 0x36: case 0x37: + { + _isLastChunk = true; + _chunkLength = (tag - 0x34) * 256 + read(); + + byte []buffer = new byte[_chunkLength]; + int k = 0; + + while ((data = parseByte()) >= 0) { + buffer[k++] = (byte) data; + } + + return buffer; + } + + default: + throw expect("bytes", tag); + } + } + + /** + * Reads a byte from the stream. + */ + public int readByte() + throws IOException + { + if (_chunkLength > 0) { + _chunkLength--; + if (_chunkLength == 0 && _isLastChunk) + _chunkLength = END_OF_DATA; + + return read(); + } + else if (_chunkLength == END_OF_DATA) { + _chunkLength = 0; + return -1; + } + + int tag = read(); + + switch (tag) { + case 'N': + return -1; + + case 'B': + case BC_BINARY_CHUNK: + _isLastChunk = tag == 'B'; + _chunkLength = (read() << 8) + read(); + + int value = parseByte(); + + // special code so successive read byte won't + // be read as a single object. + if (_chunkLength == 0 && _isLastChunk) + _chunkLength = END_OF_DATA; + + return value; + + default: + throw expect("binary", tag); + } + } + + /** + * Reads a byte array from the stream. + */ + public int readBytes(byte []buffer, int offset, int length) + throws IOException + { + int readLength = 0; + + if (_chunkLength == END_OF_DATA) { + _chunkLength = 0; + return -1; + } + else if (_chunkLength == 0) { + int tag = read(); + + switch (tag) { + case 'N': + return -1; + + case 'B': + case BC_BINARY_CHUNK: + _isLastChunk = tag == 'B'; + _chunkLength = (read() << 8) + read(); + break; + + default: + throw expect("binary", tag); + } + } + + while (length > 0) { + if (_chunkLength > 0) { + buffer[offset++] = (byte) read(); + _chunkLength--; + length--; + readLength++; + } + else if (_isLastChunk) { + if (readLength == 0) + return -1; + else { + _chunkLength = END_OF_DATA; + return readLength; + } + } + else { + int tag = read(); + + switch (tag) { + case 'B': + case BC_BINARY_CHUNK: + _isLastChunk = tag == 'B'; + _chunkLength = (read() << 8) + read(); + break; + + default: + throw expect("binary", tag); + } + } + } + + if (readLength == 0) + return -1; + else if (_chunkLength > 0 || ! _isLastChunk) + return readLength; + else { + _chunkLength = END_OF_DATA; + return readLength; + } + } + + /** + * Reads a fault. + */ + private HashMap readFault() + throws IOException + { + HashMap map = new HashMap(); + + int code = read(); + for (; code > 0 && code != 'Z'; code = read()) { + _offset--; + + Object key = readObject(); + Object value = readObject(); + + if (key != null && value != null) + map.put(key, value); + } + + if (code != 'Z') + throw expect("fault", code); + + return map; + } + + /** + * Reads an object from the input stream with an expected type. + */ + public Object readObject(Class cl) + throws IOException + { + if (cl == null || cl == Object.class) + return readObject(); + + int tag = _offset < _length ? (_buffer[_offset++] & 0xff) : read(); + + switch (tag) { + case 'N': + return null; + + case 'H': + { + Deserializer reader = findSerializerFactory().getDeserializer(cl); + + return reader.readMap(this); + } + + case 'M': + { + String type = readType(); + + // hessian/3bb3 + if ("".equals(type)) { + Deserializer reader; + reader = findSerializerFactory().getDeserializer(cl); + + return reader.readMap(this); + } + else { + Deserializer reader; + reader = findSerializerFactory().getObjectDeserializer(type, cl); + + return reader.readMap(this); + } + } + + case 'C': + { + readObjectDefinition(cl); + + return readObject(cl); + } + + case 0x60: case 0x61: case 0x62: case 0x63: + case 0x64: case 0x65: case 0x66: case 0x67: + case 0x68: case 0x69: case 0x6a: case 0x6b: + case 0x6c: case 0x6d: case 0x6e: case 0x6f: + { + int ref = tag - 0x60; + int size = _classDefs.size(); + + if (ref < 0 || size <= ref) + throw new HessianProtocolException("'" + ref + "' is an unknown class definition"); + + ObjectDefinition def = (ObjectDefinition) _classDefs.get(ref); + + return readObjectInstance(cl, def); + } + + case 'O': + { + int ref = readInt(); + int size = _classDefs.size(); + + if (ref < 0 || size <= ref) + throw new HessianProtocolException("'" + ref + "' is an unknown class definition"); + + ObjectDefinition def = (ObjectDefinition) _classDefs.get(ref); + + return readObjectInstance(cl, def); + } + + case BC_LIST_VARIABLE: + { + String type = readType(); + + Deserializer reader; + reader = findSerializerFactory().getListDeserializer(type, cl); + + Object v = reader.readList(this, -1); + + return v; + } + + case BC_LIST_FIXED: + { + String type = readType(); + int length = readInt(); + + Deserializer reader; + reader = findSerializerFactory().getListDeserializer(type, cl); + + Object v = reader.readLengthList(this, length); + + return v; + } + + case 0x70: case 0x71: case 0x72: case 0x73: + case 0x74: case 0x75: case 0x76: case 0x77: + { + int length = tag - 0x70; + + String type = readType(); + + Deserializer reader; + reader = findSerializerFactory().getListDeserializer(null, cl); + + Object v = reader.readLengthList(this, length); + + return v; + } + + case BC_LIST_VARIABLE_UNTYPED: + { + Deserializer reader; + reader = findSerializerFactory().getListDeserializer(null, cl); + + Object v = reader.readList(this, -1); + + return v; + } + + case BC_LIST_FIXED_UNTYPED: + { + int length = readInt(); + + Deserializer reader; + reader = findSerializerFactory().getListDeserializer(null, cl); + + Object v = reader.readLengthList(this, length); + + return v; + } + + case 0x78: case 0x79: case 0x7a: case 0x7b: + case 0x7c: case 0x7d: case 0x7e: case 0x7f: + { + int length = tag - 0x78; + + Deserializer reader; + reader = findSerializerFactory().getListDeserializer(null, cl); + + Object v = reader.readLengthList(this, length); + + return v; + } + + case BC_REF: + { + int ref = readInt(); + + return _refs.get(ref); + } + } + + if (tag >= 0) + _offset--; + + // hessian/3b2i vs hessian/3406 + // return readObject(); + Object value = findSerializerFactory().getDeserializer(cl).readObject(this); + return value; + } + + /** + * Reads an arbitrary object from the input stream when the type + * is unknown. + */ + public Object readObject() + throws IOException + { + int tag = _offset < _length ? (_buffer[_offset++] & 0xff) : read(); + + switch (tag) { + case 'N': + return null; + + case 'T': + return Boolean.valueOf(true); + + case 'F': + return Boolean.valueOf(false); + + // direct integer + case 0x80: case 0x81: case 0x82: case 0x83: + case 0x84: case 0x85: case 0x86: case 0x87: + case 0x88: case 0x89: case 0x8a: case 0x8b: + case 0x8c: case 0x8d: case 0x8e: case 0x8f: + + case 0x90: case 0x91: case 0x92: case 0x93: + case 0x94: case 0x95: case 0x96: case 0x97: + case 0x98: case 0x99: case 0x9a: case 0x9b: + case 0x9c: case 0x9d: case 0x9e: case 0x9f: + + case 0xa0: case 0xa1: case 0xa2: case 0xa3: + case 0xa4: case 0xa5: case 0xa6: case 0xa7: + case 0xa8: case 0xa9: case 0xaa: case 0xab: + case 0xac: case 0xad: case 0xae: case 0xaf: + + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb4: case 0xb5: case 0xb6: case 0xb7: + case 0xb8: case 0xb9: case 0xba: case 0xbb: + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + return Integer.valueOf(tag - BC_INT_ZERO); + + /* byte int */ + case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc4: case 0xc5: case 0xc6: case 0xc7: + case 0xc8: case 0xc9: case 0xca: case 0xcb: + case 0xcc: case 0xcd: case 0xce: case 0xcf: + return Integer.valueOf(((tag - BC_INT_BYTE_ZERO) << 8) + read()); + + /* short int */ + case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xd4: case 0xd5: case 0xd6: case 0xd7: + return Integer.valueOf(((tag - BC_INT_SHORT_ZERO) << 16) + + 256 * read() + read()); + + case 'I': + return Integer.valueOf(parseInt()); + + // direct long + case 0xd8: case 0xd9: case 0xda: case 0xdb: + case 0xdc: case 0xdd: case 0xde: case 0xdf: + + case 0xe0: case 0xe1: case 0xe2: case 0xe3: + case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe8: case 0xe9: case 0xea: case 0xeb: + case 0xec: case 0xed: case 0xee: case 0xef: + return Long.valueOf(tag - BC_LONG_ZERO); + + /* byte long */ + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: + return Long.valueOf(((tag - BC_LONG_BYTE_ZERO) << 8) + read()); + + /* short long */ + case 0x38: case 0x39: case 0x3a: case 0x3b: + case 0x3c: case 0x3d: case 0x3e: case 0x3f: + return Long.valueOf(((tag - BC_LONG_SHORT_ZERO) << 16) + 256 * read() + read()); + + case BC_LONG_INT: + return Long.valueOf(parseInt()); + + case 'L': + return Long.valueOf(parseLong()); + + case BC_DOUBLE_ZERO: + return Double.valueOf(0); + + case BC_DOUBLE_ONE: + return Double.valueOf(1); + + case BC_DOUBLE_BYTE: + return Double.valueOf((byte) read()); + + case BC_DOUBLE_SHORT: + return Double.valueOf((short) (256 * read() + read())); + + case BC_DOUBLE_MILL: + { + int mills = parseInt(); + + return Double.valueOf(0.001 * mills); + } + + case 'D': + return Double.valueOf(parseDouble()); + + case BC_DATE: + return new Date(parseLong()); + + case BC_DATE_MINUTE: + return new Date(parseInt() * 60000L); + + case BC_STRING_CHUNK: + case 'S': + { + _isLastChunk = tag == 'S'; + _chunkLength = (read() << 8) + read(); + + int data; + _sbuf.setLength(0); + + while ((data = parseChar()) >= 0) + _sbuf.append((char) data); + + return _sbuf.toString(); + } + + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x18: case 0x19: case 0x1a: case 0x1b: + case 0x1c: case 0x1d: case 0x1e: case 0x1f: + { + _isLastChunk = true; + _chunkLength = tag - 0x00; + + int data; + _sbuf.setLength(0); + + while ((data = parseChar()) >= 0) + _sbuf.append((char) data); + + return _sbuf.toString(); + } + + case 0x30: case 0x31: case 0x32: case 0x33: + { + _isLastChunk = true; + _chunkLength = (tag - 0x30) * 256 + read(); + + _sbuf.setLength(0); + + int ch; + while ((ch = parseChar()) >= 0) + _sbuf.append((char) ch); + + return _sbuf.toString(); + } + + case BC_BINARY_CHUNK: + case 'B': + { + _isLastChunk = tag == 'B'; + _chunkLength = (read() << 8) + read(); + + int data; + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + while ((data = parseByte()) >= 0) + bos.write(data); + + return bos.toByteArray(); + } + + case 0x20: case 0x21: case 0x22: case 0x23: + case 0x24: case 0x25: case 0x26: case 0x27: + case 0x28: case 0x29: case 0x2a: case 0x2b: + case 0x2c: case 0x2d: case 0x2e: case 0x2f: + { + _isLastChunk = true; + int len = tag - 0x20; + _chunkLength = 0; + + byte []data = new byte[len]; + + for (int i = 0; i < len; i++) + data[i] = (byte) read(); + + return data; + } + + case 0x34: case 0x35: case 0x36: case 0x37: + { + _isLastChunk = true; + int len = (tag - 0x34) * 256 + read(); + _chunkLength = 0; + + byte []buffer = new byte[len]; + + for (int i = 0; i < len; i++) { + buffer[i] = (byte) read(); + } + + return buffer; + } + + case BC_LIST_VARIABLE: + { + // variable length list + String type = readType(); + + return findSerializerFactory().readList(this, -1, type); + } + + case BC_LIST_VARIABLE_UNTYPED: + { + return findSerializerFactory().readList(this, -1, null); + } + + case BC_LIST_FIXED: + { + // fixed length lists + String type = readType(); + int length = readInt(); + + Deserializer reader; + reader = findSerializerFactory().getListDeserializer(type, null); + + return reader.readLengthList(this, length); + } + + case BC_LIST_FIXED_UNTYPED: + { + // fixed length lists + int length = readInt(); + + Deserializer reader; + reader = findSerializerFactory().getListDeserializer(null, null); + + return reader.readLengthList(this, length); + } + + // compact fixed list + case 0x70: case 0x71: case 0x72: case 0x73: + case 0x74: case 0x75: case 0x76: case 0x77: + { + // fixed length lists + String type = readType(); + int length = tag - 0x70; + + Deserializer reader; + reader = findSerializerFactory().getListDeserializer(type, null); + + return reader.readLengthList(this, length); + } + + // compact fixed untyped list + case 0x78: case 0x79: case 0x7a: case 0x7b: + case 0x7c: case 0x7d: case 0x7e: case 0x7f: + { + // fixed length lists + int length = tag - 0x78; + + Deserializer reader; + reader = findSerializerFactory().getListDeserializer(null, null); + + return reader.readLengthList(this, length); + } + + case 'H': + { + return findSerializerFactory().readMap(this, null); + } + + case 'M': + { + String type = readType(); + + return findSerializerFactory().readMap(this, type); + } + + case 'C': + { + readObjectDefinition(null); + + return readObject(); + } + + case 0x60: case 0x61: case 0x62: case 0x63: + case 0x64: case 0x65: case 0x66: case 0x67: + case 0x68: case 0x69: case 0x6a: case 0x6b: + case 0x6c: case 0x6d: case 0x6e: case 0x6f: + { + int ref = tag - 0x60; + + if (_classDefs == null) + throw error("No classes defined at reference '{0}'" + tag); + + ObjectDefinition def = (ObjectDefinition) _classDefs.get(ref); + + return readObjectInstance(null, def); + } + + case 'O': + { + int ref = readInt(); + + ObjectDefinition def = (ObjectDefinition) _classDefs.get(ref); + + return readObjectInstance(null, def); + } + + case BC_REF: + { + int ref = readInt(); + + return _refs.get(ref); + } + + default: + if (tag < 0) + throw new EOFException("readObject: unexpected end of file"); + else + throw error("readObject: unknown code " + codeName(tag)); + } + } + + /** + * Reads an object definition: + * + *
+   * O string  (string)* *
+   * 
+ */ + private void readObjectDefinition(Class cl) + throws IOException + { + String type = readString(); + int len = readInt(); + + String []fieldNames = new String[len]; + for (int i = 0; i < len; i++) + fieldNames[i] = readString(); + + ObjectDefinition def = new ObjectDefinition(type, fieldNames); + + if (_classDefs == null) + _classDefs = new ArrayList(); + + _classDefs.add(def); + } + + private Object readObjectInstance(Class cl, ObjectDefinition def) + throws IOException + { + String type = def.getType(); + String []fieldNames = def.getFieldNames(); + + if (cl != null) { + Deserializer reader; + reader = findSerializerFactory().getObjectDeserializer(type, cl); + + return reader.readObject(this, fieldNames); + } + else { + return findSerializerFactory().readObject(this, type, fieldNames); + } + } + + private String readLenString() + throws IOException + { + int len = readInt(); + + _isLastChunk = true; + _chunkLength = len; + + _sbuf.setLength(0); + int ch; + while ((ch = parseChar()) >= 0) + _sbuf.append((char) ch); + + return _sbuf.toString(); + } + + private String readLenString(int len) + throws IOException + { + _isLastChunk = true; + _chunkLength = len; + + _sbuf.setLength(0); + int ch; + while ((ch = parseChar()) >= 0) + _sbuf.append((char) ch); + + return _sbuf.toString(); + } + + /** + * Reads a remote object. + */ + public Object readRemote() + throws IOException + { + String type = readType(); + String url = readString(); + + return resolveRemote(type, url); + } + + /** + * Reads a reference. + */ + public Object readRef() + throws IOException + { + return _refs.get(parseInt()); + } + + /** + * Reads the start of a list. + */ + public int readListStart() + throws IOException + { + return read(); + } + + /** + * Reads the start of a list. + */ + public int readMapStart() + throws IOException + { + return read(); + } + + /** + * Returns true if this is the end of a list or a map. + */ + public boolean isEnd() + throws IOException + { + int code; + + if (_offset < _length) + code = (_buffer[_offset] & 0xff); + else { + code = read(); + + if (code >= 0) + _offset--; + } + + return (code < 0 || code == 'Z'); + } + + /** + * Reads the end byte. + */ + public void readEnd() + throws IOException + { + int code = _offset < _length ? (_buffer[_offset++] & 0xff) : read(); + + if (code == 'Z') + return; + else if (code < 0) + throw error("unexpected end of file"); + else + throw error("unknown code:" + codeName(code)); + } + + /** + * Reads the end byte. + */ + public void readMapEnd() + throws IOException + { + int code = _offset < _length ? (_buffer[_offset++] & 0xff) : read(); + + if (code != 'Z') + throw error("expected end of map ('Z') at '" + codeName(code) + "'"); + } + + /** + * Reads the end byte. + */ + public void readListEnd() + throws IOException + { + int code = _offset < _length ? (_buffer[_offset++] & 0xff) : read(); + + if (code != 'Z') + throw error("expected end of list ('Z') at '" + codeName(code) + "'"); + } + + /** + * Adds a list/map reference. + */ + public int addRef(Object ref) + { + if (_refs == null) + _refs = new ArrayList(); + + _refs.add(ref); + + return _refs.size() - 1; + } + + /** + * Adds a list/map reference. + */ + public void setRef(int i, Object ref) + { + _refs.set(i, ref); + } + + /** + * Resets the references for streaming. + */ + public void resetReferences() + { + if (_refs != null) + _refs.clear(); + } + + public Object readStreamingObject() + throws IOException + { + if (_refs != null) + _refs.clear(); + + return readObject(); + } + + /** + * Resolves a remote object. + */ + public Object resolveRemote(String type, String url) + throws IOException + { + HessianRemoteResolver resolver = getRemoteResolver(); + + if (resolver != null) + return resolver.lookup(type, url); + else + return new HessianRemote(type, url); + } + + /** + * Parses a type from the stream. + * + *
+   * type ::= string
+   * type ::= int
+   * 
+ */ + public String readType() + throws IOException + { + int code = _offset < _length ? (_buffer[_offset++] & 0xff) : read(); + _offset--; + + switch (code) { + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x18: case 0x19: case 0x1a: case 0x1b: + case 0x1c: case 0x1d: case 0x1e: case 0x1f: + + case 0x30: case 0x31: case 0x32: case 0x33: + case BC_STRING_CHUNK: case 'S': + { + String type = readString(); + + if (_types == null) + _types = new ArrayList(); + + _types.add(type); + + return type; + } + + default: + { + int ref = readInt(); + + if (_types.size() <= ref) + throw new IndexOutOfBoundsException("type ref #" + ref + " is greater than the number of valid types (" + _types.size() + ")"); + + return (String) _types.get(ref); + } + } + } + + /** + * Parses the length for an array + * + *
+   * l b32 b24 b16 b8
+   * 
+ */ + public int readLength() + throws IOException + { + throw new UnsupportedOperationException(); + } + + /** + * Parses a 32-bit integer value from the stream. + * + *
+   * b32 b24 b16 b8
+   * 
+ */ + private int parseInt() + throws IOException + { + int offset = _offset; + + if (offset + 3 < _length) { + byte []buffer = _buffer; + + int b32 = buffer[offset + 0] & 0xff; + int b24 = buffer[offset + 1] & 0xff; + int b16 = buffer[offset + 2] & 0xff; + int b8 = buffer[offset + 3] & 0xff; + + _offset = offset + 4; + + return (b32 << 24) + (b24 << 16) + (b16 << 8) + b8; + } + else { + int b32 = read(); + int b24 = read(); + int b16 = read(); + int b8 = read(); + + return (b32 << 24) + (b24 << 16) + (b16 << 8) + b8; + } + } + + /** + * Parses a 64-bit long value from the stream. + * + *
+   * b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ */ + private long parseLong() + throws IOException + { + long b64 = read(); + long b56 = read(); + long b48 = read(); + long b40 = read(); + long b32 = read(); + long b24 = read(); + long b16 = read(); + long b8 = read(); + + return ((b64 << 56) + + (b56 << 48) + + (b48 << 40) + + (b40 << 32) + + (b32 << 24) + + (b24 << 16) + + (b16 << 8) + + b8); + } + + /** + * Parses a 64-bit double value from the stream. + * + *
+   * b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ */ + private double parseDouble() + throws IOException + { + long bits = parseLong(); + + return Double.longBitsToDouble(bits); + } + + org.w3c.dom.Node parseXML() + throws IOException + { + throw new UnsupportedOperationException(); + } + + /** + * Reads a character from the underlying stream. + */ + private int parseChar() + throws IOException + { + while (_chunkLength <= 0) { + if (_isLastChunk) + return -1; + + int code = _offset < _length ? (_buffer[_offset++] & 0xff) : read(); + + switch (code) { + case BC_STRING_CHUNK: + _isLastChunk = false; + + _chunkLength = (read() << 8) + read(); + break; + + case 'S': + _isLastChunk = true; + + _chunkLength = (read() << 8) + read(); + break; + + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x18: case 0x19: case 0x1a: case 0x1b: + case 0x1c: case 0x1d: case 0x1e: case 0x1f: + _isLastChunk = true; + _chunkLength = code - 0x00; + break; + + // qian.lei 2010-7-21 + case 0x30: case 0x31: case 0x32: case 0x33: + _isLastChunk = true; + _chunkLength = ((code - 0x30) << 8) + read(); + break; + + default: + throw expect("string", code); + } + + } + + _chunkLength--; + + return parseUTF8Char(); + } + + /** + * Parses a single UTF8 character. + */ + private int parseUTF8Char() + throws IOException + { + int ch = _offset < _length ? (_buffer[_offset++] & 0xff) : read(); + + if (ch < 0x80) + return ch; + else if ((ch & 0xe0) == 0xc0) { + int ch1 = read(); + int v = ((ch & 0x1f) << 6) + (ch1 & 0x3f); + + return v; + } + else if ((ch & 0xf0) == 0xe0) { + int ch1 = read(); + int ch2 = read(); + int v = ((ch & 0x0f) << 12) + ((ch1 & 0x3f) << 6) + (ch2 & 0x3f); + + return v; + } + else + throw error("bad utf-8 encoding at " + codeName(ch)); + } + + /** + * Reads a byte from the underlying stream. + */ + private int parseByte() + throws IOException + { + while (_chunkLength <= 0) { + if (_isLastChunk) { + return -1; + } + + int code = read(); + + switch (code) { + case BC_BINARY_CHUNK: + _isLastChunk = false; + + _chunkLength = (read() << 8) + read(); + break; + + case 'B': + _isLastChunk = true; + + _chunkLength = (read() << 8) + read(); + break; + + case 0x20: case 0x21: case 0x22: case 0x23: + case 0x24: case 0x25: case 0x26: case 0x27: + case 0x28: case 0x29: case 0x2a: case 0x2b: + case 0x2c: case 0x2d: case 0x2e: case 0x2f: + _isLastChunk = true; + + _chunkLength = code - 0x20; + break; + + case 0x34: case 0x35: case 0x36: case 0x37: + _isLastChunk = true; + _chunkLength = (code - 0x34) * 256 + read(); + break; + + default: + throw expect("byte[]", code); + } + } + + _chunkLength--; + + return read(); + } + + /** + * Reads bytes based on an input stream. + */ + public InputStream readInputStream() + throws IOException + { + int tag = read(); + + switch (tag) { + case 'N': + return null; + + case 'B': + case 'b': + _isLastChunk = tag == 'B'; + _chunkLength = (read() << 8) + read(); + break; + + case 0x20: case 0x21: case 0x22: case 0x23: + case 0x24: case 0x25: case 0x26: case 0x27: + case 0x28: case 0x29: case 0x2a: case 0x2b: + case 0x2c: case 0x2d: case 0x2e: case 0x2f: + _isLastChunk = true; + _chunkLength = tag - 0x20; + break; + + default: + throw expect("binary", tag); + } + + return new ReadInputStream(); + } + + /** + * Reads bytes from the underlying stream. + */ + int read(byte []buffer, int offset, int length) + throws IOException + { + int readLength = 0; + + while (length > 0) { + while (_chunkLength <= 0) { + if (_isLastChunk) + return readLength == 0 ? -1 : readLength; + + int code = read(); + + switch (code) { + case 'b': + _isLastChunk = false; + + _chunkLength = (read() << 8) + read(); + break; + + case 'B': + _isLastChunk = true; + + _chunkLength = (read() << 8) + read(); + break; + + case 0x20: case 0x21: case 0x22: case 0x23: + case 0x24: case 0x25: case 0x26: case 0x27: + case 0x28: case 0x29: case 0x2a: case 0x2b: + case 0x2c: case 0x2d: case 0x2e: case 0x2f: + _isLastChunk = true; + _chunkLength = code - 0x20; + break; + + default: + throw expect("byte[]", code); + } + } + + int sublen = _chunkLength; + if (length < sublen) + sublen = length; + + if (_length <= _offset && ! readBuffer()) + return -1; + + if (_length - _offset < sublen) + sublen = _length - _offset; + + System.arraycopy(_buffer, _offset, buffer, offset, sublen); + + _offset += sublen; + + offset += sublen; + readLength += sublen; + length -= sublen; + _chunkLength -= sublen; + } + + return readLength; + } + + /** + * Normally, shouldn't be called externally, but needed for QA, e.g. + * ejb/3b01. + */ + public final int read() + throws IOException + { + if (_length <= _offset && ! readBuffer()) + return -1; + + return _buffer[_offset++] & 0xff; + } + + private final boolean readBuffer() + throws IOException + { + byte []buffer = _buffer; + int offset = _offset; + int length = _length; + + if (offset < length) { + System.arraycopy(buffer, offset, buffer, 0, length - offset); + offset = length - offset; + } + else + offset = 0; + + int len = _is.read(buffer, offset, SIZE - offset); + + if (len <= 0) { + _length = offset; + _offset = 0; + + return offset > 0; + } + + _length = offset + len; + _offset = 0; + + return true; + } + + public Reader getReader() + { + return null; + } + + protected IOException expect(String expect, int ch) + throws IOException + { + if (ch < 0) + return error("expected " + expect + " at end of file"); + else { + _offset--; + + try { + Object obj = readObject(); + + if (obj != null) { + return error("expected " + expect + + " at 0x" + Integer.toHexString(ch & 0xff) + + " " + obj.getClass().getName() + " (" + obj + ")"); + } + else + return error("expected " + expect + + " at 0x" + Integer.toHexString(ch & 0xff) + " null"); + } catch (IOException e) { + log.log(Level.FINE, e.toString(), e); + + return error("expected " + expect + + " at 0x" + Integer.toHexString(ch & 0xff)); + } + } + } + + protected String codeName(int ch) + { + if (ch < 0) + return "end of file"; + else + return "0x" + Integer.toHexString(ch & 0xff) + " (" + (char) + ch + ")"; + } + + protected IOException error(String message) + { + if (_method != null) + return new HessianProtocolException(_method + ": " + message); + else + return new HessianProtocolException(message); + } + + public void close() + throws IOException + { + InputStream is = _is; + _is = null; + + if (_isCloseStreamOnClose && is != null) + is.close(); + } + + class ReadInputStream extends InputStream { + boolean _isClosed = false; + + public int read() + throws IOException + { + if (_isClosed) + return -1; + + int ch = parseByte(); + if (ch < 0) + _isClosed = true; + + return ch; + } + + public int read(byte []buffer, int offset, int length) + throws IOException + { + if (_isClosed) + return -1; + + int len = Hessian2Input.this.read(buffer, offset, length); + if (len < 0) + _isClosed = true; + + return len; + } + + public void close() + throws IOException + { + while (read() >= 0) { + } + } + }; + + final static class ObjectDefinition { + private final String _type; + private final String []_fields; + + ObjectDefinition(String type, String []fields) + { + _type = type; + _fields = fields; + } + + String getType() + { + return _type; + } + + String []getFieldNames() + { + return _fields; + } + } + + static { + try { + _detailMessageField = Throwable.class.getDeclaredField("detailMessage"); + _detailMessageField.setAccessible(true); + } catch (Throwable e) { + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2Output.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2Output.java new file mode 100644 index 000000000000..657d4d2edde8 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2Output.java @@ -0,0 +1,1605 @@ +/* + * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import com.alibaba.com.caucho.hessian.util.IdentityIntMap; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.HashMap; + +/** + * Output stream for Hessian 2 requests. + * + *

Since HessianOutput does not depend on any classes other than + * in the JDK, it can be extracted independently into a smaller package. + * + *

HessianOutput is unbuffered, so any client needs to provide + * its own buffering. + * + *

+ * OutputStream os = ...; // from http connection
+ * Hessian2Output out = new Hessian2Output(os);
+ * String value;
+ *
+ * out.startCall("hello", 1); // start hello call
+ * out.writeString("arg1");   // write a string argument
+ * out.completeCall();        // complete the call
+ * 
+ */ +public class Hessian2Output + extends AbstractHessianOutput + implements Hessian2Constants +{ + // the output stream/ + protected OutputStream _os; + + // map of references + private IdentityIntMap _refs = new IdentityIntMap(); + + private boolean _isCloseStreamOnClose; + + // map of classes + private HashMap _classRefs; + + // map of types + private HashMap _typeRefs; + + public final static int SIZE = 4096; + + private final byte []_buffer = new byte[SIZE]; + private int _offset; + + private boolean _isStreaming; + + /** + * Creates a new Hessian output stream, initialized with an + * underlying output stream. + * + * @param os the underlying output stream. + */ + public Hessian2Output(OutputStream os) + { + _os = os; + } + + public void setCloseStreamOnClose(boolean isClose) + { + _isCloseStreamOnClose = isClose; + } + + public boolean isCloseStreamOnClose() + { + return _isCloseStreamOnClose; + } + + + /** + * Writes a complete method call. + */ + @Override + public void call(String method, Object []args) + throws IOException + { + int length = args != null ? args.length : 0; + + startCall(method, length); + + for (int i = 0; i < args.length; i++) + writeObject(args[i]); + + completeCall(); + } + + /** + * Starts the method call. Clients would use startCall + * instead of call if they wanted finer control over + * writing the arguments, or needed to write headers. + * + *
+   * C
+   * string # method name
+   * int    # arg count
+   * 
+ * + * @param method the method name to call. + */ + public void startCall(String method, int length) + throws IOException + { + int offset = _offset; + + if (SIZE < offset + 32) { + flush(); + offset = _offset; + } + + byte []buffer = _buffer; + + buffer[_offset++] = (byte) 'C'; + + writeString(method); + writeInt(length); + } + + /** + * Writes the call tag. This would be followed by the + * method and the arguments + * + *
+   * C
+   * 
+ * + * @param method the method name to call. + */ + public void startCall() + throws IOException + { + flushIfFull(); + + _buffer[_offset++] = (byte) 'C'; + } + + /** + * Starts an envelope. + * + *
+   * E major minor
+   * m b16 b8 method-name
+   * 
+ * + * @param method the method name to call. + */ + public void startEnvelope(String method) + throws IOException + { + int offset = _offset; + + if (SIZE < offset + 32) { + flush(); + offset = _offset; + } + + _buffer[_offset++] = (byte) 'E'; + + writeString(method); + } + + /** + * Completes an envelope. + * + *

A successful completion will have a single value: + * + *

+   * Z
+   * 
+ */ + public void completeEnvelope() + throws IOException + { + flushIfFull(); + + _buffer[_offset++] = (byte) 'Z'; + } + + /** + * Writes the method tag. + * + *
+   * string
+   * 
+ * + * @param method the method name to call. + */ + public void writeMethod(String method) + throws IOException + { + writeString(method); + } + + /** + * Completes. + * + *
+   * z
+   * 
+ */ + public void completeCall() + throws IOException + { + /* + flushIfFull(); + + _buffer[_offset++] = (byte) 'Z'; + */ + } + + /** + * Starts the reply + * + *

A successful completion will have a single value: + * + *

+   * R
+   * 
+ */ + public void startReply() + throws IOException + { + writeVersion(); + + flushIfFull(); + + _buffer[_offset++] = (byte) 'R'; + } + + public void writeVersion() + throws IOException + { + flushIfFull(); + _buffer[_offset++] = (byte) 'H'; + _buffer[_offset++] = (byte) 2; + _buffer[_offset++] = (byte) 0; + } + + /** + * Completes reading the reply + * + *

A successful completion will have a single value: + * + *

+   * z
+   * 
+ */ + public void completeReply() + throws IOException + { + } + + /** + * Starts a packet + * + *

A message contains several objects encapsulated by a length

+ * + *
+   * p x02 x00
+   * 
+ */ + public void startMessage() + throws IOException + { + flushIfFull(); + + _buffer[_offset++] = (byte) 'p'; + _buffer[_offset++] = (byte) 2; + _buffer[_offset++] = (byte) 0; + } + + /** + * Completes reading the message + * + *

A successful completion will have a single value: + * + *

+   * z
+   * 
+ */ + public void completeMessage() + throws IOException + { + flushIfFull(); + + _buffer[_offset++] = (byte) 'z'; + } + + /** + * Writes a fault. The fault will be written + * as a descriptive string followed by an object: + * + *
+   * F map
+   * 
+ * + *
+   * F H
+   * \x04code
+   * \x10the fault code
+   *
+   * \x07message
+   * \x11the fault message
+   *
+   * \x06detail
+   * M\xnnjavax.ejb.FinderException
+   *     ...
+   * Z
+   * Z
+   * 
+ * + * @param code the fault code, a three digit + */ + public void writeFault(String code, String message, Object detail) + throws IOException + { + flushIfFull(); + + writeVersion(); + + _buffer[_offset++] = (byte) 'F'; + _buffer[_offset++] = (byte) 'H'; + + _refs.put(new HashMap(), _refs.size()); + + writeString("code"); + writeString(code); + + writeString("message"); + writeString(message); + + if (detail != null) { + writeString("detail"); + writeObject(detail); + } + + flushIfFull(); + _buffer[_offset++] = (byte) 'Z'; + } + + /** + * Writes any object to the output stream. + */ + public void writeObject(Object object) + throws IOException + { + if (object == null) { + writeNull(); + return; + } + + Serializer serializer; + + serializer = findSerializerFactory().getSerializer(object.getClass()); + + serializer.writeObject(object, this); + } + + /** + * Writes the list header to the stream. List writers will call + * writeListBegin followed by the list contents and then + * call writeListEnd. + * + *
+   * list ::= V type value* Z
+   *      ::= v type int value*
+   * 
+ * + * @return true for variable lists, false for fixed lists + */ + public boolean writeListBegin(int length, String type) + throws IOException + { + flushIfFull(); + + if (length < 0) { + if (type != null) { + _buffer[_offset++] = (byte) BC_LIST_VARIABLE; + writeType(type); + } + else + _buffer[_offset++] = (byte) BC_LIST_VARIABLE_UNTYPED; + + return true; + } + else if (length <= LIST_DIRECT_MAX) { + if (type != null) { + _buffer[_offset++] = (byte) (BC_LIST_DIRECT + length); + writeType(type); + } + else { + _buffer[_offset++] = (byte) (BC_LIST_DIRECT_UNTYPED + length); + } + + return false; + } + else { + if (type != null) { + _buffer[_offset++] = (byte) BC_LIST_FIXED; + writeType(type); + } + else { + _buffer[_offset++] = (byte) BC_LIST_FIXED_UNTYPED; + } + + writeInt(length); + + return false; + } + } + + /** + * Writes the tail of the list to the stream for a variable-length list. + */ + public void writeListEnd() + throws IOException + { + flushIfFull(); + + _buffer[_offset++] = (byte) BC_END; + } + + /** + * Writes the map header to the stream. Map writers will call + * writeMapBegin followed by the map contents and then + * call writeMapEnd. + * + *
+   * map ::= M type ( )* Z
+   *     ::= H ( )* Z
+   * 
+ */ + public void writeMapBegin(String type) + throws IOException + { + if (SIZE < _offset + 32) + flush(); + + if (type != null) { + _buffer[_offset++] = BC_MAP; + + writeType(type); + } + else + _buffer[_offset++] = BC_MAP_UNTYPED; + } + + /** + * Writes the tail of the map to the stream. + */ + public void writeMapEnd() + throws IOException + { + if (SIZE < _offset + 32) + flush(); + + _buffer[_offset++] = (byte) BC_END; + } + + /** + * Writes the object definition + * + *
+   * C <string> <int> <string>*
+   * 
+ */ + public int writeObjectBegin(String type) + throws IOException + { + if (_classRefs == null) + _classRefs = new HashMap(); + + Integer refV = (Integer) _classRefs.get(type); + + if (refV != null) { + int ref = refV.intValue(); + + if (SIZE < _offset + 32) + flush(); + + if (ref <= OBJECT_DIRECT_MAX) { + _buffer[_offset++] = (byte) (BC_OBJECT_DIRECT + ref); + } + else { + _buffer[_offset++] = (byte) 'O'; + writeInt(ref); + } + + return ref; + } + else { + int ref = _classRefs.size(); + + _classRefs.put(type, Integer.valueOf(ref)); + + if (SIZE < _offset + 32) + flush(); + + _buffer[_offset++] = (byte) 'C'; + + writeString(type); + + return -1; + } + } + + /** + * Writes the tail of the class definition to the stream. + */ + public void writeClassFieldLength(int len) + throws IOException + { + writeInt(len); + } + + /** + * Writes the tail of the object definition to the stream. + */ + public void writeObjectEnd() + throws IOException + { + } + + /** + *
+   * type ::= string
+   *      ::= int
+   * 
+ */ + private void writeType(String type) + throws IOException + { + flushIfFull(); + + int len = type.length(); + if (len == 0) { + throw new IllegalArgumentException("empty type is not allowed"); + } + + if (_typeRefs == null) + _typeRefs = new HashMap(); + + Integer typeRefV = (Integer) _typeRefs.get(type); + + if (typeRefV != null) { + int typeRef = typeRefV.intValue(); + + writeInt(typeRef); + } + else { + _typeRefs.put(type, Integer.valueOf(_typeRefs.size())); + + writeString(type); + } + } + + /** + * Writes a boolean value to the stream. The boolean will be written + * with the following syntax: + * + *
+   * T
+   * F
+   * 
+ * + * @param value the boolean value to write. + */ + public void writeBoolean(boolean value) + throws IOException + { + if (SIZE < _offset + 16) + flush(); + + if (value) + _buffer[_offset++] = (byte) 'T'; + else + _buffer[_offset++] = (byte) 'F'; + } + + /** + * Writes an integer value to the stream. The integer will be written + * with the following syntax: + * + *
+   * I b32 b24 b16 b8
+   * 
+ * + * @param value the integer value to write. + */ + public void writeInt(int value) + throws IOException + { + int offset = _offset; + byte []buffer = _buffer; + + if (SIZE <= offset + 16) { + flush(); + offset = _offset; + } + + if (INT_DIRECT_MIN <= value && value <= INT_DIRECT_MAX) + buffer[offset++] = (byte) (value + BC_INT_ZERO); + else if (INT_BYTE_MIN <= value && value <= INT_BYTE_MAX) { + buffer[offset++] = (byte) (BC_INT_BYTE_ZERO + (value >> 8)); + buffer[offset++] = (byte) (value); + } + else if (INT_SHORT_MIN <= value && value <= INT_SHORT_MAX) { + buffer[offset++] = (byte) (BC_INT_SHORT_ZERO + (value >> 16)); + buffer[offset++] = (byte) (value >> 8); + buffer[offset++] = (byte) (value); + } + else { + buffer[offset++] = (byte) ('I'); + buffer[offset++] = (byte) (value >> 24); + buffer[offset++] = (byte) (value >> 16); + buffer[offset++] = (byte) (value >> 8); + buffer[offset++] = (byte) (value); + } + + _offset = offset; + } + + /** + * Writes a long value to the stream. The long will be written + * with the following syntax: + * + *
+   * L b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ * + * @param value the long value to write. + */ + public void writeLong(long value) + throws IOException + { + int offset = _offset; + byte []buffer = _buffer; + + if (SIZE <= offset + 16) { + flush(); + offset = _offset; + } + + if (LONG_DIRECT_MIN <= value && value <= LONG_DIRECT_MAX) { + buffer[offset++] = (byte) (value + BC_LONG_ZERO); + } + else if (LONG_BYTE_MIN <= value && value <= LONG_BYTE_MAX) { + buffer[offset++] = (byte) (BC_LONG_BYTE_ZERO + (value >> 8)); + buffer[offset++] = (byte) (value); + } + else if (LONG_SHORT_MIN <= value && value <= LONG_SHORT_MAX) { + buffer[offset++] = (byte) (BC_LONG_SHORT_ZERO + (value >> 16)); + buffer[offset++] = (byte) (value >> 8); + buffer[offset++] = (byte) (value); + } + else if (-0x80000000L <= value && value <= 0x7fffffffL) { + buffer[offset + 0] = (byte) BC_LONG_INT; + buffer[offset + 1] = (byte) (value >> 24); + buffer[offset + 2] = (byte) (value >> 16); + buffer[offset + 3] = (byte) (value >> 8); + buffer[offset + 4] = (byte) (value); + + offset += 5; + } + else { + buffer[offset + 0] = (byte) 'L'; + buffer[offset + 1] = (byte) (value >> 56); + buffer[offset + 2] = (byte) (value >> 48); + buffer[offset + 3] = (byte) (value >> 40); + buffer[offset + 4] = (byte) (value >> 32); + buffer[offset + 5] = (byte) (value >> 24); + buffer[offset + 6] = (byte) (value >> 16); + buffer[offset + 7] = (byte) (value >> 8); + buffer[offset + 8] = (byte) (value); + + offset += 9; + } + + _offset = offset; + } + + /** + * Writes a double value to the stream. The double will be written + * with the following syntax: + * + *
+   * D b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ * + * @param value the double value to write. + */ + public void writeDouble(double value) + throws IOException + { + int offset = _offset; + byte []buffer = _buffer; + + if (SIZE <= offset + 16) { + flush(); + offset = _offset; + } + + int intValue = (int) value; + + if (intValue == value) { + if (intValue == 0) { + buffer[offset++] = (byte) BC_DOUBLE_ZERO; + + _offset = offset; + + return; + } + else if (intValue == 1) { + buffer[offset++] = (byte) BC_DOUBLE_ONE; + + _offset = offset; + + return; + } + else if (-0x80 <= intValue && intValue < 0x80) { + buffer[offset++] = (byte) BC_DOUBLE_BYTE; + buffer[offset++] = (byte) intValue; + + _offset = offset; + + return; + } + else if (-0x8000 <= intValue && intValue < 0x8000) { + buffer[offset + 0] = (byte) BC_DOUBLE_SHORT; + buffer[offset + 1] = (byte) (intValue >> 8); + buffer[offset + 2] = (byte) intValue; + + _offset = offset + 3; + + return; + } + } + + int mills = (int) (value * 1000); + + if (0.001 * mills == value) { + buffer[offset + 0] = (byte) (BC_DOUBLE_MILL); + buffer[offset + 1] = (byte) (mills >> 24); + buffer[offset + 2] = (byte) (mills >> 16); + buffer[offset + 3] = (byte) (mills >> 8); + buffer[offset + 4] = (byte) (mills); + + _offset = offset + 5; + + return; + } + + long bits = Double.doubleToLongBits(value); + + buffer[offset + 0] = (byte) 'D'; + buffer[offset + 1] = (byte) (bits >> 56); + buffer[offset + 2] = (byte) (bits >> 48); + buffer[offset + 3] = (byte) (bits >> 40); + buffer[offset + 4] = (byte) (bits >> 32); + buffer[offset + 5] = (byte) (bits >> 24); + buffer[offset + 6] = (byte) (bits >> 16); + buffer[offset + 7] = (byte) (bits >> 8); + buffer[offset + 8] = (byte) (bits); + + _offset = offset + 9; + } + + /** + * Writes a date to the stream. + * + *
+   * date ::= d   b7 b6 b5 b4 b3 b2 b1 b0
+   *      ::= x65 b3 b2 b1 b0
+   * 
+ * + * @param time the date in milliseconds from the epoch in UTC + */ + public void writeUTCDate(long time) + throws IOException + { + if (SIZE < _offset + 32) + flush(); + + int offset = _offset; + byte []buffer = _buffer; + + if (time % 60000L == 0) { + // compact date ::= x65 b3 b2 b1 b0 + + long minutes = time / 60000L; + + if ((minutes >> 31) == 0 || (minutes >> 31) == -1) { + buffer[offset++] = (byte) BC_DATE_MINUTE; + buffer[offset++] = ((byte) (minutes >> 24)); + buffer[offset++] = ((byte) (minutes >> 16)); + buffer[offset++] = ((byte) (minutes >> 8)); + buffer[offset++] = ((byte) (minutes >> 0)); + + _offset = offset; + return; + } + } + + buffer[offset++] = (byte) BC_DATE; + buffer[offset++] = ((byte) (time >> 56)); + buffer[offset++] = ((byte) (time >> 48)); + buffer[offset++] = ((byte) (time >> 40)); + buffer[offset++] = ((byte) (time >> 32)); + buffer[offset++] = ((byte) (time >> 24)); + buffer[offset++] = ((byte) (time >> 16)); + buffer[offset++] = ((byte) (time >> 8)); + buffer[offset++] = ((byte) (time)); + + _offset = offset; + } + + /** + * Writes a null value to the stream. + * The null will be written with the following syntax + * + *
+   * N
+   * 
+ * + * @param value the string value to write. + */ + public void writeNull() + throws IOException + { + int offset = _offset; + byte []buffer = _buffer; + + if (SIZE <= offset + 16) { + flush(); + offset = _offset; + } + + buffer[offset++] = 'N'; + + _offset = offset; + } + + /** + * Writes a string value to the stream using UTF-8 encoding. + * The string will be written with the following syntax: + * + *
+   * S b16 b8 string-value
+   * 
+ * + * If the value is null, it will be written as + * + *
+   * N
+   * 
+ * + * @param value the string value to write. + */ + public void writeString(String value) + throws IOException + { + int offset = _offset; + byte []buffer = _buffer; + + if (SIZE <= offset + 16) { + flush(); + offset = _offset; + } + + if (value == null) { + buffer[offset++] = (byte) 'N'; + + _offset = offset; + } + else { + int length = value.length(); + int strOffset = 0; + + while (length > 0x8000) { + int sublen = 0x8000; + + offset = _offset; + + if (SIZE <= offset + 16) { + flush(); + offset = _offset; + } + + // chunk can't end in high surrogate + char tail = value.charAt(strOffset + sublen - 1); + + if (0xd800 <= tail && tail <= 0xdbff) + sublen--; + + buffer[offset + 0] = (byte) BC_STRING_CHUNK; + buffer[offset + 1] = (byte) (sublen >> 8); + buffer[offset + 2] = (byte) (sublen); + + _offset = offset + 3; + + printString(value, strOffset, sublen); + + length -= sublen; + strOffset += sublen; + } + + offset = _offset; + + if (SIZE <= offset + 16) { + flush(); + offset = _offset; + } + + if (length <= STRING_DIRECT_MAX) { + buffer[offset++] = (byte) (BC_STRING_DIRECT + length); + } + else if (length <= STRING_SHORT_MAX) { + buffer[offset++] = (byte) (BC_STRING_SHORT + (length >> 8)); + buffer[offset++] = (byte) (length); + } + else { + buffer[offset++] = (byte) ('S'); + buffer[offset++] = (byte) (length >> 8); + buffer[offset++] = (byte) (length); + } + + _offset = offset; + + printString(value, strOffset, length); + } + } + + /** + * Writes a string value to the stream using UTF-8 encoding. + * The string will be written with the following syntax: + * + *
+   * S b16 b8 string-value
+   * 
+ * + * If the value is null, it will be written as + * + *
+   * N
+   * 
+ * + * @param value the string value to write. + */ + public void writeString(char []buffer, int offset, int length) + throws IOException + { + if (buffer == null) { + if (SIZE < _offset + 16) + flush(); + + _buffer[_offset++] = (byte) ('N'); + } + else { + while (length > 0x8000) { + int sublen = 0x8000; + + if (SIZE < _offset + 16) + flush(); + + // chunk can't end in high surrogate + char tail = buffer[offset + sublen - 1]; + + if (0xd800 <= tail && tail <= 0xdbff) + sublen--; + + _buffer[_offset++] = (byte) BC_STRING_CHUNK; + _buffer[_offset++] = (byte) (sublen >> 8); + _buffer[_offset++] = (byte) (sublen); + + printString(buffer, offset, sublen); + + length -= sublen; + offset += sublen; + } + + if (SIZE < _offset + 16) + flush(); + + if (length <= STRING_DIRECT_MAX) { + _buffer[_offset++] = (byte) (BC_STRING_DIRECT + length); + } + else if (length <= STRING_SHORT_MAX) { + _buffer[_offset++] = (byte) (BC_STRING_SHORT + (length >> 8)); + _buffer[_offset++] = (byte) length; + } + else { + _buffer[_offset++] = (byte) ('S'); + _buffer[_offset++] = (byte) (length >> 8); + _buffer[_offset++] = (byte) (length); + } + + printString(buffer, offset, length); + } + } + + /** + * Writes a byte array to the stream. + * The array will be written with the following syntax: + * + *
+   * B b16 b18 bytes
+   * 
+ * + * If the value is null, it will be written as + * + *
+   * N
+   * 
+ * + * @param value the string value to write. + */ + public void writeBytes(byte []buffer) + throws IOException + { + if (buffer == null) { + if (SIZE < _offset + 16) + flush(); + + _buffer[_offset++] = 'N'; + } + else + writeBytes(buffer, 0, buffer.length); + } + + /** + * Writes a byte array to the stream. + * The array will be written with the following syntax: + * + *
+   * B b16 b18 bytes
+   * 
+ * + * If the value is null, it will be written as + * + *
+   * N
+   * 
+ * + * @param value the string value to write. + */ + public void writeBytes(byte []buffer, int offset, int length) + throws IOException + { + if (buffer == null) { + if (SIZE < _offset + 16) + flushBuffer(); + + _buffer[_offset++] = (byte) 'N'; + } + else { + flush(); + + while (SIZE - _offset - 3 < length) { + int sublen = SIZE - _offset - 3; + + if (sublen < 16) { + flushBuffer(); + + sublen = SIZE - _offset - 3; + + if (length < sublen) + sublen = length; + } + + _buffer[_offset++] = (byte) BC_BINARY_CHUNK; + _buffer[_offset++] = (byte) (sublen >> 8); + _buffer[_offset++] = (byte) sublen; + + System.arraycopy(buffer, offset, _buffer, _offset, sublen); + _offset += sublen; + + length -= sublen; + offset += sublen; + + flushBuffer(); + } + + if (SIZE < _offset + 16) + flushBuffer(); + + if (length <= BINARY_DIRECT_MAX) { + _buffer[_offset++] = (byte) (BC_BINARY_DIRECT + length); + } + else if (length <= BINARY_SHORT_MAX) { + _buffer[_offset++] = (byte) (BC_BINARY_SHORT + (length >> 8)); + _buffer[_offset++] = (byte) (length); + } + else { + _buffer[_offset++] = (byte) 'B'; + _buffer[_offset++] = (byte) (length >> 8); + _buffer[_offset++] = (byte) (length); + } + + System.arraycopy(buffer, offset, _buffer, _offset, length); + + _offset += length; + } + } + + /** + * Writes a byte buffer to the stream. + * + *
+   * 
+ */ + public void writeByteBufferStart() + throws IOException + { + } + + /** + * Writes a byte buffer to the stream. + * + *
+   * b b16 b18 bytes
+   * 
+ */ + public void writeByteBufferPart(byte []buffer, int offset, int length) + throws IOException + { + while (length > 0) { + int sublen = length; + + if (0x8000 < sublen) + sublen = 0x8000; + + flush(); // bypass buffer + + _os.write(BC_BINARY_CHUNK); + _os.write(sublen >> 8); + _os.write(sublen); + + _os.write(buffer, offset, sublen); + + length -= sublen; + offset += sublen; + } + } + + /** + * Writes a byte buffer to the stream. + * + *
+   * b b16 b18 bytes
+   * 
+ */ + public void writeByteBufferEnd(byte []buffer, int offset, int length) + throws IOException + { + writeBytes(buffer, offset, length); + } + + /** + * Returns an output stream to write binary data. + */ + public OutputStream getBytesOutputStream() + throws IOException + { + return new BytesOutputStream(); + } + + /** + * Writes a reference. + * + *
+   * x51 <int>
+   * 
+ * + * @param value the integer value to write. + */ + @Override + protected void writeRef(int value) + throws IOException + { + if (SIZE < _offset + 16) + flush(); + + _buffer[_offset++] = (byte) BC_REF; + + writeInt(value); + } + + /** + * If the object has already been written, just write its ref. + * + * @return true if we're writing a ref. + */ + public boolean addRef(Object object) + throws IOException + { + int ref = _refs.get(object); + + if (ref >= 0) { + writeRef(ref); + + return true; + } + else { + _refs.put(object, _refs.size()); + + return false; + } + } + + /** + * Removes a reference. + */ + public boolean removeRef(Object obj) + throws IOException + { + if (_refs != null) { + _refs.remove(obj); + + return true; + } + else + return false; + } + + /** + * Replaces a reference from one object to another. + */ + public boolean replaceRef(Object oldRef, Object newRef) + throws IOException + { + Integer value = (Integer) _refs.remove(oldRef); + + if (value != null) { + _refs.put(newRef, value); + return true; + } + else + return false; + } + + /** + * Resets the references for streaming. + */ + public void resetReferences() + { + if (_refs != null) + _refs.clear(); + } + + /** + * Starts the streaming message + * + *

A streaming message starts with 'P'

+ * + *
+   * P x02 x00
+   * 
+ */ + public void writeStreamingObject(Object obj) + throws IOException + { + startStreamingPacket(); + + writeObject(obj); + + endStreamingPacket(); + } + + /** + * Starts a streaming packet + * + *

A streaming message starts with 'P'

+ * + *
+   * P x02 x00
+   * 
+ */ + public void startStreamingPacket() + throws IOException + { + if (_refs != null) + _refs.clear(); + + flush(); + + _isStreaming = true; + _offset = 3; + } + + public void endStreamingPacket() + throws IOException + { + int len = _offset - 3; + + _buffer[0] = (byte) 'P'; + _buffer[1] = (byte) (len >> 8); + _buffer[2] = (byte) len; + + _isStreaming = false; + + flush(); + } + + /** + * Prints a string to the stream, encoded as UTF-8 with preceeding length + * + * @param v the string to print. + */ + public void printLenString(String v) + throws IOException + { + if (SIZE < _offset + 16) + flush(); + + if (v == null) { + _buffer[_offset++] = (byte) (0); + _buffer[_offset++] = (byte) (0); + } + else { + int len = v.length(); + _buffer[_offset++] = (byte) (len >> 8); + _buffer[_offset++] = (byte) (len); + + printString(v, 0, len); + } + } + + /** + * Prints a string to the stream, encoded as UTF-8 + * + * @param v the string to print. + */ + public void printString(String v) + throws IOException + { + printString(v, 0, v.length()); + } + + /** + * Prints a string to the stream, encoded as UTF-8 + * + * @param v the string to print. + */ + public void printString(String v, int strOffset, int length) + throws IOException + { + int offset = _offset; + byte []buffer = _buffer; + + for (int i = 0; i < length; i++) { + if (SIZE <= offset + 16) { + _offset = offset; + flush(); + offset = _offset; + } + + char ch = v.charAt(i + strOffset); + + if (ch < 0x80) + buffer[offset++] = (byte) (ch); + else if (ch < 0x800) { + buffer[offset++] = (byte) (0xc0 + ((ch >> 6) & 0x1f)); + buffer[offset++] = (byte) (0x80 + (ch & 0x3f)); + } + else { + buffer[offset++] = (byte) (0xe0 + ((ch >> 12) & 0xf)); + buffer[offset++] = (byte) (0x80 + ((ch >> 6) & 0x3f)); + buffer[offset++] = (byte) (0x80 + (ch & 0x3f)); + } + } + + _offset = offset; + } + + /** + * Prints a string to the stream, encoded as UTF-8 + * + * @param v the string to print. + */ + public void printString(char []v, int strOffset, int length) + throws IOException + { + int offset = _offset; + byte []buffer = _buffer; + + for (int i = 0; i < length; i++) { + if (SIZE <= offset + 16) { + _offset = offset; + flush(); + offset = _offset; + } + + char ch = v[i + strOffset]; + + if (ch < 0x80) + buffer[offset++] = (byte) (ch); + else if (ch < 0x800) { + buffer[offset++] = (byte) (0xc0 + ((ch >> 6) & 0x1f)); + buffer[offset++] = (byte) (0x80 + (ch & 0x3f)); + } + else { + buffer[offset++] = (byte) (0xe0 + ((ch >> 12) & 0xf)); + buffer[offset++] = (byte) (0x80 + ((ch >> 6) & 0x3f)); + buffer[offset++] = (byte) (0x80 + (ch & 0x3f)); + } + } + + _offset = offset; + } + + private final void flushIfFull() + throws IOException + { + int offset = _offset; + + if (SIZE < offset + 32) { + _offset = 0; + _os.write(_buffer, 0, offset); + } + } + + public final void flush() + throws IOException + { + flushBuffer(); + + if (_os != null) + _os.flush(); + } + + public final void flushBuffer() + throws IOException + { + int offset = _offset; + + if (! _isStreaming && offset > 0) { + _offset = 0; + + _os.write(_buffer, 0, offset); + } + else if (_isStreaming && offset > 3) { + int len = offset - 3; + _buffer[0] = 'p'; + _buffer[1] = (byte) (len >> 8); + _buffer[2] = (byte) len; + _offset = 3; + + _os.write(_buffer, 0, offset); + } + } + + public final void close() + throws IOException + { + // hessian/3a8c + flush(); + + OutputStream os = _os; + _os = null; + + if (os != null) { + if (_isCloseStreamOnClose) + os.close(); + } + } + + class BytesOutputStream extends OutputStream { + private int _startOffset; + + BytesOutputStream() + throws IOException + { + if (SIZE < _offset + 16) { + Hessian2Output.this.flush(); + } + + _startOffset = _offset; + _offset += 3; // skip 'b' xNN xNN + } + + @Override + public void write(int ch) + throws IOException + { + if (SIZE <= _offset) { + int length = (_offset - _startOffset) - 3; + + _buffer[_startOffset] = (byte) BC_BINARY_CHUNK; + _buffer[_startOffset + 1] = (byte) (length >> 8); + _buffer[_startOffset + 2] = (byte) (length); + + Hessian2Output.this.flush(); + + _startOffset = _offset; + _offset += 3; + } + + _buffer[_offset++] = (byte) ch; + } + + @Override + public void write(byte []buffer, int offset, int length) + throws IOException + { + while (length > 0) { + int sublen = SIZE - _offset; + + if (length < sublen) + sublen = length; + + if (sublen > 0) { + System.arraycopy(buffer, offset, _buffer, _offset, sublen); + _offset += sublen; + } + + length -= sublen; + offset += sublen; + + if (SIZE <= _offset) { + int chunkLength = (_offset - _startOffset) - 3; + + _buffer[_startOffset] = (byte) BC_BINARY_CHUNK; + _buffer[_startOffset + 1] = (byte) (chunkLength >> 8); + _buffer[_startOffset + 2] = (byte) (chunkLength); + + Hessian2Output.this.flush(); + + _startOffset = _offset; + _offset += 3; + } + } + } + + @Override + public void close() + throws IOException + { + int startOffset = _startOffset; + _startOffset = -1; + + if (startOffset < 0) + return; + + int length = (_offset - startOffset) - 3; + + _buffer[startOffset] = (byte) 'B'; + _buffer[startOffset + 1] = (byte) (length >> 8); + _buffer[startOffset + 2] = (byte) (length); + + Hessian2Output.this.flush(); + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2StreamingInput.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2StreamingInput.java new file mode 100644 index 000000000000..ac8e8e9d9fdf --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2StreamingInput.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Output stream for Hessian 2 streaming requests. + */ +public class Hessian2StreamingInput +{ + private Hessian2Input _in; + + /** + * Creates a new Hessian input stream, initialized with an + * underlying input stream. + * + * @param is the underlying output stream. + */ + public Hessian2StreamingInput(InputStream is) + { + _in = new Hessian2Input(new StreamingInputStream(is)); + } + + /** + * Read the next object + */ + public Object readObject() + throws IOException + { + return _in.readStreamingObject(); + } + + /** + * Close the output. + */ + public void close() + throws IOException + { + _in.close(); + } + + static class StreamingInputStream extends InputStream { + private InputStream _is; + private int _length; + + StreamingInputStream(InputStream is) + { + _is = is; + } + + public int read() + throws IOException + { + InputStream is = _is; + + while (_length == 0) { + int code = is.read(); + + if (code < 0) + return -1; + else if (code != 'p' && code != 'P') + throw new HessianProtocolException("expected streaming packet at 0x" + + Integer.toHexString(code & 0xff)); + + int d1 = is.read(); + int d2 = is.read(); + + if (d2 < 0) + return -1; + + _length = (d1 << 8) + d2; + } + + _length--; + return is.read(); + } + + public int read(byte []buffer, int offset, int length) + throws IOException + { + InputStream is = _is; + + while (_length == 0) { + int code = is.read(); + + if (code < 0) + return -1; + else if (code != 'p' && code != 'P') { + throw new HessianProtocolException("expected streaming packet at 0x" + + Integer.toHexString(code & 0xff) + + " (" + (char) code + ")"); + } + + int d1 = is.read(); + int d2 = is.read(); + + if (d2 < 0) + return -1; + + _length = (d1 << 8) + d2; + } + + int sublen = _length; + if (length < sublen) + sublen = length; + + sublen = is.read(buffer, offset, sublen); + + if (sublen < 0) + return -1; + + _length -= sublen; + + return sublen; + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2StreamingOutput.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2StreamingOutput.java new file mode 100644 index 000000000000..28c44cdf5805 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2StreamingOutput.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.HashMap; + +/** + * Output stream for Hessian 2 streaming requests. + */ +public class Hessian2StreamingOutput +{ + private Hessian2Output _out; + + /** + * Creates a new Hessian output stream, initialized with an + * underlying output stream. + * + * @param os the underlying output stream. + */ + public Hessian2StreamingOutput(OutputStream os) + { + _out = new Hessian2Output(os); + } + + public void setCloseStreamOnClose(boolean isClose) + { + _out.setCloseStreamOnClose(isClose); + } + + public boolean isCloseStreamOnClose() + { + return _out.isCloseStreamOnClose(); + } + + /** + * Writes any object to the output stream. + */ + public void writeObject(Object object) + throws IOException + { + _out.writeStreamingObject(object); + } + + /** + * Flushes the output. + */ + public void flush() + throws IOException + { + _out.flush(); + } + + /** + * Close the output. + */ + public void close() + throws IOException + { + _out.close(); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianDebugInputStream.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianDebugInputStream.java new file mode 100644 index 000000000000..31e1f2881a14 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianDebugInputStream.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Writer; +import java.io.PrintWriter; +import java.util.ArrayList; + +import java.util.logging.Logger; +import java.util.logging.Level; + +/** + * Debugging input stream for Hessian requests. + */ +public class HessianDebugInputStream extends InputStream +{ + private InputStream _is; + + private HessianDebugState _state; + + /** + * Creates an uninitialized Hessian input stream. + */ + public HessianDebugInputStream(InputStream is, PrintWriter dbg) + { + _is = is; + + if (dbg == null) + dbg = new PrintWriter(System.out); + + _state = new HessianDebugState(dbg); + } + + /** + * Creates an uninitialized Hessian input stream. + */ + public HessianDebugInputStream(InputStream is, Logger log, Level level) + { + this(is, new PrintWriter(new LogWriter(log, level))); + } + + public void startTop2() + { + _state.startTop2(); + } + + /** + * Reads a character. + */ + public int read() + throws IOException + { + int ch; + + InputStream is = _is; + + if (is == null) + return -1; + else { + ch = is.read(); + } + + _state.next(ch); + + return ch; + } + + /** + * closes the stream. + */ + public void close() + throws IOException + { + InputStream is = _is; + _is = null; + + if (is != null) + is.close(); + + _state.println(); + } + + static class LogWriter extends Writer { + private Logger _log; + private Level _level; + private StringBuilder _sb = new StringBuilder(); + + LogWriter(Logger log, Level level) + { + _log = log; + _level = level; + } + + public void write(char ch) + { + if (ch == '\n' && _sb.length() > 0) { + _log.log(_level, _sb.toString()); + _sb.setLength(0); + } + else + _sb.append((char) ch); + } + + public void write(char []buffer, int offset, int length) + { + for (int i = 0; i < length; i++) { + char ch = buffer[offset + i]; + + if (ch == '\n' && _sb.length() > 0) { + _log.log(_level, _sb.toString()); + _sb.setLength(0); + } + else + _sb.append((char) ch); + } + } + + public void flush() + { + } + + public void close() + { + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianDebugOutputStream.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianDebugOutputStream.java new file mode 100644 index 000000000000..0511e664f2cc --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianDebugOutputStream.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; +import java.io.PrintWriter; + +import java.util.logging.Logger; +import java.util.logging.Level; + +/** + * Debugging output stream for Hessian requests. + */ +public class HessianDebugOutputStream extends OutputStream +{ + private OutputStream _os; + + private HessianDebugState _state; + + /** + * Creates an uninitialized Hessian input stream. + */ + public HessianDebugOutputStream(OutputStream os, PrintWriter dbg) + { + _os = os; + + _state = new HessianDebugState(dbg); + } + + /** + * Creates an uninitialized Hessian input stream. + */ + public HessianDebugOutputStream(OutputStream os, Logger log, Level level) + { + this(os, new PrintWriter(new LogWriter(log, level))); + } + + public void startTop2() + { + _state.startTop2(); + } + + /** + * Writes a character. + */ + public void write(int ch) + throws IOException + { + ch = ch & 0xff; + + _os.write(ch); + + _state.next(ch); + } + + public void flush() + throws IOException + { + _os.flush(); + } + + /** + * closes the stream. + */ + public void close() + throws IOException + { + OutputStream os = _os; + _os = null; + + if (os != null) + os.close(); + + _state.println(); + } + + static class LogWriter extends Writer { + private Logger _log; + private Level _level; + private StringBuilder _sb = new StringBuilder(); + + LogWriter(Logger log, Level level) + { + _log = log; + _level = level; + } + + public void write(char ch) + { + if (ch == '\n' && _sb.length() > 0) { + _log.log(_level, _sb.toString()); + _sb.setLength(0); + } + else + _sb.append((char) ch); + } + + public void write(char []buffer, int offset, int length) + { + for (int i = 0; i < length; i++) { + char ch = buffer[offset + i]; + + if (ch == '\n' && _sb.length() > 0) { + _log.log(_level, _sb.toString()); + _sb.setLength(0); + } + else + _sb.append((char) ch); + } + } + + public void flush() + { + } + + public void close() + { + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianDebugState.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianDebugState.java new file mode 100644 index 000000000000..89239e842f9d --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianDebugState.java @@ -0,0 +1,2090 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.util.ArrayList; + +/** + * Debugging input stream for Hessian requests. + */ +public class HessianDebugState implements Hessian2Constants +{ + private PrintWriter _dbg; + + private State _state; + private ArrayList _stateStack = new ArrayList(); + + private ArrayList _objectDefList + = new ArrayList(); + + private ArrayList _typeDefList + = new ArrayList(); + + private int _refId; + private boolean _isNewline = true; + private boolean _isObject = false; + private int _column; + + /** + * Creates an uninitialized Hessian input stream. + */ + public HessianDebugState(PrintWriter dbg) + { + _dbg = dbg; + + _state = new InitialState(); + } + + public void startTop2() + { + _state = new Top2State(); + } + + /** + * Reads a character. + */ + public void next(int ch) + throws IOException + { + _state = _state.next(ch); + } + + void pushStack(State state) + { + _stateStack.add(state); + } + + State popStack() + { + return _stateStack.remove(_stateStack.size() - 1); + } + + void println() + { + if (! _isNewline) { + _dbg.println(); + _dbg.flush(); + } + + _isNewline = true; + _column = 0; + } + + static boolean isString(int ch) + { + switch (ch) { + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x18: case 0x19: case 0x1a: case 0x1b: + case 0x1c: case 0x1d: case 0x1e: case 0x1f: + + case 0x30: case 0x31: case 0x32: case 0x33: + + case 'R': + case 'S': + return true; + + default: + return false; + } + } + + static boolean isInteger(int ch) + { + switch (ch) { + case 0x80: case 0x81: case 0x82: case 0x83: + case 0x84: case 0x85: case 0x86: case 0x87: + case 0x88: case 0x89: case 0x8a: case 0x8b: + case 0x8c: case 0x8d: case 0x8e: case 0x8f: + + case 0x90: case 0x91: case 0x92: case 0x93: + case 0x94: case 0x95: case 0x96: case 0x97: + case 0x98: case 0x99: case 0x9a: case 0x9b: + case 0x9c: case 0x9d: case 0x9e: case 0x9f: + + case 0xa0: case 0xa1: case 0xa2: case 0xa3: + case 0xa4: case 0xa5: case 0xa6: case 0xa7: + case 0xa8: case 0xa9: case 0xaa: case 0xab: + case 0xac: case 0xad: case 0xae: case 0xaf: + + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb4: case 0xb5: case 0xb6: case 0xb7: + case 0xb8: case 0xb9: case 0xba: case 0xbb: + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + + case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc4: case 0xc5: case 0xc6: case 0xc7: + case 0xc8: case 0xc9: case 0xca: case 0xcb: + case 0xcc: case 0xcd: case 0xce: case 0xcf: + + case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xd4: case 0xd5: case 0xd6: case 0xd7: + + case 'I': + return true; + + default: + return false; + } + } + + abstract class State { + State _next; + + State() + { + } + + State(State next) + { + _next = next; + } + + abstract State next(int ch); + + boolean isShift(Object value) + { + return false; + } + + State shift(Object value) + { + return this; + } + + int depth() + { + if (_next != null) + return _next.depth(); + else + return 0; + } + + void printIndent(int depth) + { + if (_isNewline) { + for (int i = _column; i < depth() + depth; i++) { + _dbg.print(" "); + _column++; + } + } + } + + void print(String string) + { + print(0, string); + } + + void print(int depth, String string) + { + printIndent(depth); + + _dbg.print(string); + _isNewline = false; + _isObject = false; + + int p = string.lastIndexOf('\n'); + if (p > 0) + _column = string.length() - p - 1; + else + _column += string.length(); + } + + void println(String string) + { + println(0, string); + } + + void println(int depth, String string) + { + printIndent(depth); + + _dbg.println(string); + _dbg.flush(); + _isNewline = true; + _isObject = false; + _column = 0; + } + + void println() + { + if (! _isNewline) { + _dbg.println(); + _dbg.flush(); + } + + _isNewline = true; + _isObject = false; + _column = 0; + } + + void printObject(String string) + { + if (_isObject) + println(); + + printIndent(0); + + _dbg.print(string); + _dbg.flush(); + + _column += string.length(); + + _isNewline = false; + _isObject = true; + } + + protected State nextObject(int ch) + { + switch (ch) { + case -1: + println(); + return this; + + case 'N': + if (isShift(null)) + return shift(null); + else { + printObject("null"); + return this; + } + + case 'T': + if (isShift(Boolean.TRUE)) + return shift(Boolean.TRUE); + else { + printObject("true"); + return this; + } + + case 'F': + if (isShift(Boolean.FALSE)) + return shift(Boolean.FALSE); + else { + printObject("false"); + return this; + } + + case 0x80: case 0x81: case 0x82: case 0x83: + case 0x84: case 0x85: case 0x86: case 0x87: + case 0x88: case 0x89: case 0x8a: case 0x8b: + case 0x8c: case 0x8d: case 0x8e: case 0x8f: + + case 0x90: case 0x91: case 0x92: case 0x93: + case 0x94: case 0x95: case 0x96: case 0x97: + case 0x98: case 0x99: case 0x9a: case 0x9b: + case 0x9c: case 0x9d: case 0x9e: case 0x9f: + + case 0xa0: case 0xa1: case 0xa2: case 0xa3: + case 0xa4: case 0xa5: case 0xa6: case 0xa7: + case 0xa8: case 0xa9: case 0xaa: case 0xab: + case 0xac: case 0xad: case 0xae: case 0xaf: + + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb4: case 0xb5: case 0xb6: case 0xb7: + case 0xb8: case 0xb9: case 0xba: case 0xbb: + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + { + Integer value = new Integer(ch - 0x90); + + if (isShift(value)) + return shift(value); + else { + printObject(value.toString()); + return this; + } + } + + case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc4: case 0xc5: case 0xc6: case 0xc7: + case 0xc8: case 0xc9: case 0xca: case 0xcb: + case 0xcc: case 0xcd: case 0xce: case 0xcf: + return new IntegerState(this, "int", ch - 0xc8, 3); + + case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xd4: case 0xd5: case 0xd6: case 0xd7: + return new IntegerState(this, "int", ch - 0xd4, 2); + + case 'I': + return new IntegerState(this, "int"); + + case 0xd8: case 0xd9: case 0xda: case 0xdb: + case 0xdc: case 0xdd: case 0xde: case 0xdf: + case 0xe0: case 0xe1: case 0xe2: case 0xe3: + case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe8: case 0xe9: case 0xea: case 0xeb: + case 0xec: case 0xed: case 0xee: case 0xef: + { + Long value = new Long(ch - 0xe0); + + if (isShift(value)) + return shift(value); + else { + printObject(value.toString() + "L"); + return this; + } + } + + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: + return new LongState(this, "long", ch - 0xf8, 7); + + case 0x38: case 0x39: case 0x3a: case 0x3b: + case 0x3c: case 0x3d: case 0x3e: case 0x3f: + return new LongState(this, "long", ch - 0x3c, 6); + + case BC_LONG_INT: + return new LongState(this, "long", 0, 4); + + case 'L': + return new LongState(this, "long"); + + case 0x5b: case 0x5c: + { + Double value = new Double(ch - 0x5b); + + if (isShift(value)) + return shift(value); + else { + printObject(value.toString()); + return this; + } + } + + case 0x5d: + return new DoubleIntegerState(this, 3); + + case 0x5e: + return new DoubleIntegerState(this, 2); + + case 0x5f: + return new MillsState(this); + + case 'D': + return new DoubleState(this); + + case 'Q': + return new RefState(this); + + case BC_DATE: + return new DateState(this); + + case BC_DATE_MINUTE: + return new DateState(this, true); + + case 0x00: + { + String value = "\"\""; + + if (isShift(value)) + return shift(value); + else { + printObject(value.toString()); + return this; + } + } + + case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x18: case 0x19: case 0x1a: case 0x1b: + case 0x1c: case 0x1d: case 0x1e: case 0x1f: + return new StringState(this, 'S', ch); + + case 0x30: case 0x31: case 0x32: case 0x33: + return new StringState(this, 'S', ch - 0x30, true); + + case 'R': + return new StringState(this, 'S', false); + + case 'S': + return new StringState(this, 'S', true); + + case 0x20: + { + String value = "binary(0)"; + + if (isShift(value)) + return shift(value); + else { + printObject(value.toString()); + return this; + } + } + + case 0x21: case 0x22: case 0x23: + case 0x24: case 0x25: case 0x26: case 0x27: + case 0x28: case 0x29: case 0x2a: case 0x2b: + case 0x2c: case 0x2d: case 0x2e: case 0x2f: + return new BinaryState(this, 'B', ch - 0x20); + + case 0x34: case 0x35: case 0x36: case 0x37: + return new BinaryState(this, 'B', ch - 0x34, true); + + case 'A': + return new BinaryState(this, 'B', false); + + case 'B': + return new BinaryState(this, 'B', true); + + case 'M': + return new MapState(this, _refId++); + + case 'H': + return new MapState(this, _refId++, false); + + case BC_LIST_VARIABLE: + return new ListState(this, _refId++, true); + + case BC_LIST_VARIABLE_UNTYPED: + return new ListState(this, _refId++, false); + + case BC_LIST_FIXED: + return new CompactListState(this, _refId++, true); + + case BC_LIST_FIXED_UNTYPED: + return new CompactListState(this, _refId++, false); + + case 0x70: case 0x71: case 0x72: case 0x73: + case 0x74: case 0x75: case 0x76: case 0x77: + return new CompactListState(this, _refId++, true, ch - 0x70); + + case 0x78: case 0x79: case 0x7a: case 0x7b: + case 0x7c: case 0x7d: case 0x7e: case 0x7f: + return new CompactListState(this, _refId++, false, ch - 0x78); + + case 'C': + return new ObjectDefState(this); + + case 0x60: case 0x61: case 0x62: case 0x63: + case 0x64: case 0x65: case 0x66: case 0x67: + case 0x68: case 0x69: case 0x6a: case 0x6b: + case 0x6c: case 0x6d: case 0x6e: case 0x6f: + return new ObjectState(this, _refId++, ch - 0x60); + + case 'O': + return new ObjectState(this, _refId++); + + default: + return this; + } + } + } + + class InitialState extends State { + State next(int ch) + { + println(); + + if (ch == 'r') { + return new ReplyState(this); + } + else if (ch == 'c') { + return new CallState(this); + } + else + return nextObject(ch); + } + } + + class Top2State extends State { + State next(int ch) + { + println(); + + if (ch == 'R') { + return new Reply2State(this); + } + else if (ch == 'F') { + return new Fault2State(this); + } + else if (ch == 'C') { + return new Call2State(this); + } + else if (ch == 'H') { + return new Hessian2State(this); + } + else if (ch == 'r') { + return new ReplyState(this); + } + else if (ch == 'c') { + return new CallState(this); + } + else + return nextObject(ch); + } + } + + class IntegerState extends State { + String _typeCode; + + int _length; + int _value; + + IntegerState(State next, String typeCode) + { + super(next); + + _typeCode = typeCode; + } + + IntegerState(State next, String typeCode, int value, int length) + { + super(next); + + _typeCode = typeCode; + + _value = value; + _length = length; + } + + State next(int ch) + { + _value = 256 * _value + (ch & 0xff); + + if (++_length == 4) { + Integer value = new Integer(_value); + + if (_next.isShift(value)) + return _next.shift(value); + else { + printObject(value.toString()); + + return _next; + } + } + else + return this; + } + } + + class LongState extends State { + String _typeCode; + + int _length; + long _value; + + LongState(State next, String typeCode) + { + super(next); + + _typeCode = typeCode; + } + + LongState(State next, String typeCode, long value, int length) + { + super(next); + + _typeCode = typeCode; + + _value = value; + _length = length; + } + + State next(int ch) + { + _value = 256 * _value + (ch & 0xff); + + if (++_length == 8) { + Long value = new Long(_value); + + if (_next.isShift(value)) + return _next.shift(value); + else { + printObject(value.toString() + "L"); + + return _next; + } + } + else + return this; + } + } + + class DoubleIntegerState extends State { + int _length; + int _value; + boolean _isFirst = true; + + DoubleIntegerState(State next, int length) + { + super(next); + + _length = length; + } + + State next(int ch) + { + if (_isFirst) + _value = (byte) ch; + else + _value = 256 * _value + (ch & 0xff); + + _isFirst = false; + + if (++_length == 4) { + Double value = new Double(_value); + + if (_next.isShift(value)) + return _next.shift(value); + else { + printObject(value.toString()); + + return _next; + } + } + else + return this; + } + } + + class RefState extends State { + String _typeCode; + + int _length; + int _value; + + RefState(State next) + { + super(next); + } + + RefState(State next, String typeCode) + { + super(next); + + _typeCode = typeCode; + } + + RefState(State next, String typeCode, int value, int length) + { + super(next); + + _typeCode = typeCode; + + _value = value; + _length = length; + } + + @Override + boolean isShift(Object o) + { + return true; + } + + @Override + State shift(Object o) + { + println("ref #" + o); + + return _next; + } + + @Override + State next(int ch) + { + return nextObject(ch); + } + } + + class DateState extends State { + int _length; + long _value; + boolean _isMinute; + + DateState(State next) + { + super(next); + } + + DateState(State next, boolean isMinute) + { + super(next); + + _length = 4; + _isMinute = isMinute; + } + + + State next(int ch) + { + _value = 256 * _value + (ch & 0xff); + + if (++_length == 8) { + java.util.Date value; + + if (_isMinute) + value = new java.util.Date(_value * 60000L); + else + value = new java.util.Date(_value); + + if (_next.isShift(value)) + return _next.shift(value); + else { + printObject(value.toString()); + + return _next; + } + } + else + return this; + } + } + + class DoubleState extends State { + int _length; + long _value; + + DoubleState(State next) + { + super(next); + } + + State next(int ch) + { + _value = 256 * _value + (ch & 0xff); + + if (++_length == 8) { + Double value = Double.longBitsToDouble(_value); + + if (_next.isShift(value)) + return _next.shift(value); + else { + printObject(value.toString()); + + return _next; + } + } + else + return this; + } + } + + class MillsState extends State { + int _length; + int _value; + + MillsState(State next) + { + super(next); + } + + State next(int ch) + { + _value = 256 * _value + (ch & 0xff); + + if (++_length == 4) { + Double value = 0.001 * _value; + + if (_next.isShift(value)) + return _next.shift(value); + else { + printObject(value.toString()); + + return _next; + } + } + else + return this; + } + } + + class StringState extends State { + private static final int TOP = 0; + private static final int UTF_2_1 = 1; + private static final int UTF_3_1 = 2; + private static final int UTF_3_2 = 3; + + char _typeCode; + + StringBuilder _value = new StringBuilder(); + int _lengthIndex; + int _length; + boolean _isLastChunk; + + int _utfState; + char _ch; + + StringState(State next, char typeCode, boolean isLastChunk) + { + super(next); + + _typeCode = typeCode; + _isLastChunk = isLastChunk; + } + + StringState(State next, char typeCode, int length) + { + super(next); + + _typeCode = typeCode; + _isLastChunk = true; + _length = length; + _lengthIndex = 2; + } + + StringState(State next, char typeCode, int length, boolean isLastChunk) + { + super(next); + + _typeCode = typeCode; + _isLastChunk = isLastChunk; + _length = length; + _lengthIndex = 1; + } + + State next(int ch) + { + if (_lengthIndex < 2) { + _length = 256 * _length + (ch & 0xff); + + if (++_lengthIndex == 2 && _length == 0 && _isLastChunk) { + if (_next.isShift(_value.toString())) + return _next.shift(_value.toString()); + else { + printObject("\"" + _value + "\""); + return _next; + } + } + else + return this; + } + else if (_length == 0) { + if (ch == 's' || ch == 'x') { + _isLastChunk = false; + _lengthIndex = 0; + return this; + } + else if (ch == 'S' || ch == 'X') { + _isLastChunk = true; + _lengthIndex = 0; + return this; + } + else if (ch == 0x00) { + if (_next.isShift(_value.toString())) + return _next.shift(_value.toString()); + else { + printObject("\"" + _value + "\""); + return _next; + } + } + else if (0x00 <= ch && ch < 0x20) { + _isLastChunk = true; + _lengthIndex = 2; + _length = ch & 0xff; + return this; + } + else if (0x30 <= ch && ch < 0x34) { + _isLastChunk = true; + _lengthIndex = 1; + _length = (ch - 0x30); + return this; + } + else { + println(String.valueOf((char) ch) + ": unexpected character"); + return _next; + } + } + + switch (_utfState) { + case TOP: + if (ch < 0x80) { + _length--; + + _value.append((char) ch); + } + else if (ch < 0xe0) { + _ch = (char) ((ch & 0x1f) << 6); + _utfState = UTF_2_1; + } + else { + _ch = (char) ((ch & 0xf) << 12); + _utfState = UTF_3_1; + } + break; + + case UTF_2_1: + case UTF_3_2: + _ch += ch & 0x3f; + _value.append(_ch); + _length--; + _utfState = TOP; + break; + + case UTF_3_1: + _ch += (char) ((ch & 0x3f) << 6); + _utfState = UTF_3_2; + break; + } + + if (_length == 0 && _isLastChunk) { + if (_next.isShift(_value.toString())) + return _next.shift(_value.toString()); + else { + printObject("\"" + _value + "\""); + + return _next; + } + } + else + return this; + } + } + + class BinaryState extends State { + char _typeCode; + + int _totalLength; + + int _lengthIndex; + int _length; + boolean _isLastChunk; + + BinaryState(State next, char typeCode, boolean isLastChunk) + { + super(next); + + _typeCode = typeCode; + _isLastChunk = isLastChunk; + } + + BinaryState(State next, char typeCode, int length) + { + super(next); + + _typeCode = typeCode; + _isLastChunk = true; + _length = length; + _lengthIndex = 2; + } + + BinaryState(State next, char typeCode, int length, boolean isLastChunk) + { + super(next); + + _typeCode = typeCode; + _isLastChunk = isLastChunk; + _length = length; + _lengthIndex = 1; + } + + State next(int ch) + { + if (_lengthIndex < 2) { + _length = 256 * _length + (ch & 0xff); + + if (++_lengthIndex == 2 && _length == 0 && _isLastChunk) { + String value = "binary(" + _totalLength + ")"; + + if (_next.isShift(value)) + return _next.shift(value); + else { + printObject(value); + return _next; + } + } + else + return this; + } + else if (_length == 0) { + if (ch == 'b') { + _isLastChunk = false; + _lengthIndex = 0; + return this; + } + else if (ch == 'B') { + _isLastChunk = true; + _lengthIndex = 0; + return this; + } + else if (ch == 0x20) { + String value = "binary(" + _totalLength + ")"; + + if (_next.isShift(value)) + return _next.shift(value); + else { + printObject(value); + return _next; + } + } + else if (0x20 <=ch && ch < 0x30) { + _isLastChunk = true; + _lengthIndex = 2; + _length = (ch & 0xff) - 0x20; + return this; + } + else { + println(String.valueOf((char) ch) + ": unexpected character"); + return _next; + } + } + + _length--; + _totalLength++; + + if (_length == 0 && _isLastChunk) { + String value = "binary(" + _totalLength + ")"; + + if (_next.isShift(value)) + return _next.shift(value); + else { + printObject(value); + + return _next; + } + } + else + return this; + } + } + + class MapState extends State { + private static final int TYPE = 0; + private static final int KEY = 1; + private static final int VALUE = 2; + + private int _refId; + + private int _state; + private int _valueDepth; + private boolean _hasData; + + MapState(State next, int refId) + { + super(next); + + _refId = refId; + _state = TYPE; + } + + MapState(State next, int refId, boolean isType) + { + super(next); + + _refId = refId; + + if (isType) + _state = TYPE; + else { + printObject("map (#" + _refId + ")"); + _state = VALUE; + } + } + + @Override + boolean isShift(Object value) + { + return _state == TYPE; + } + + @Override + State shift(Object type) + { + if (_state == TYPE) { + if (type instanceof String) { + _typeDefList.add((String) type); + } + else if (type instanceof Integer) { + int iValue = (Integer) type; + + if (iValue >= 0 && iValue < _typeDefList.size()) + type = _typeDefList.get(iValue); + } + + printObject("map " + type + " (#" + _refId + ")"); + + _state = VALUE; + + return this; + } + else + throw new IllegalStateException(); + } + + @Override + int depth() + { + if (_state == TYPE) + return _next.depth(); + else if (_state == KEY) + return _next.depth() + 2; + else + return _valueDepth; + } + + State next(int ch) + { + switch (_state) { + case TYPE: + return nextObject(ch); + + case VALUE: + if (ch == 'Z') { + if (_hasData) + println(); + + return _next; + } + else { + if (_hasData) + println(); + + _hasData = true; + _state = KEY; + + return nextObject(ch); + } + + case KEY: + print(" => "); + _isObject = false; + _valueDepth = _column; + + _state = VALUE; + + return nextObject(ch); + + default: + throw new IllegalStateException(); + } + } + } + + class ObjectDefState extends State { + private static final int TYPE = 1; + private static final int COUNT = 2; + private static final int FIELD = 3; + private static final int COMPLETE = 4; + + private int _refId; + + private int _state; + private boolean _hasData; + private int _count; + + private String _type; + private ArrayList _fields = new ArrayList(); + + ObjectDefState(State next) + { + super(next); + + _state = TYPE; + } + + @Override + boolean isShift(Object value) + { + return true; + } + + @Override + State shift(Object object) + { + if (_state == TYPE) { + _type = (String) object; + + print("/* defun " + _type + " ["); + + _objectDefList.add(new ObjectDef(_type, _fields)); + + _state = COUNT; + } + else if (_state == COUNT) { + _count = (Integer) object; + + _state = FIELD; + } + else if (_state == FIELD) { + String field = (String) object; + + _count--; + + _fields.add(field); + + if (_fields.size() == 1) + print(field); + else + print(", " + field); + } + else { + throw new UnsupportedOperationException(); + } + + return this; + } + + @Override + int depth() + { + if (_state <= TYPE) + return _next.depth(); + else + return _next.depth() + 2; + } + + State next(int ch) + { + switch (_state) { + case TYPE: + return nextObject(ch); + + case COUNT: + return nextObject(ch); + + case FIELD: + if (_count == 0) { + println("] */"); + _next.printIndent(0); + + return _next.nextObject(ch); + } + else + return nextObject(ch); + + default: + throw new IllegalStateException(); + } + } + } + + class ObjectState extends State { + private static final int TYPE = 0; + private static final int FIELD = 1; + + private int _refId; + + private int _state; + private ObjectDef _def; + private int _count; + private int _fieldDepth; + + ObjectState(State next, int refId) + { + super(next); + + _refId = refId; + _state = TYPE; + } + + ObjectState(State next, int refId, int def) + { + super(next); + + _refId = refId; + _state = FIELD; + + if (def < 0 || _objectDefList.size() <= def) { + throw new IllegalStateException(def + " is an unknown object type"); + } + + _def = _objectDefList.get(def); + + println("object " + _def.getType() + " (#" + _refId + ")"); + } + + @Override + boolean isShift(Object value) + { + if (_state == TYPE) + return true; + else + return false; + } + + @Override + State shift(Object object) + { + if (_state == TYPE) { + int def = (Integer) object; + + _def = _objectDefList.get(def); + + println("object " + _def.getType() + " (#" + _refId + ")"); + + _state = FIELD; + + if (_def.getFields().size() == 0) + return _next; + } + + return this; + } + + @Override + int depth() + { + if (_state <= TYPE) + return _next.depth(); + else + return _fieldDepth; + } + + State next(int ch) + { + switch (_state) { + case TYPE: + return nextObject(ch); + + case FIELD: + if (_def.getFields().size() <= _count) + return _next.next(ch); + + _fieldDepth = _next.depth() + 2; + println(); + print(_def.getFields().get(_count++) + ": "); + + _fieldDepth = _column; + + _isObject = false; + return nextObject(ch); + + default: + throw new IllegalStateException(); + } + } + } + + class ListState extends State { + private static final int TYPE = 0; + private static final int LENGTH = 1; + private static final int VALUE = 2; + + private int _refId; + + private int _state; + private boolean _hasData; + private int _count; + private int _valueDepth; + + ListState(State next, int refId, boolean isType) + { + super(next); + + _refId = refId; + + if (isType) + _state = TYPE; + else { + printObject("list (#" + _refId + ")"); + _state = VALUE; + } + } + + @Override + boolean isShift(Object value) + { + return _state == TYPE || _state == LENGTH; + } + + @Override + State shift(Object object) + { + if (_state == TYPE) { + Object type = object; + + if (type instanceof String) { + _typeDefList.add((String) type); + } + else if (object instanceof Integer) { + int index = (Integer) object; + + if (index >= 0 && index < _typeDefList.size()) + type = _typeDefList.get(index); + else + type = "type-unknown(" + index + ")"; + } + + printObject("list " + type + "(#" + _refId + ")"); + + _state = VALUE; + + return this; + } + else if (_state == LENGTH) { + _state = VALUE; + + return this; + } + else + return this; + } + + @Override + int depth() + { + if (_state <= LENGTH) + return _next.depth(); + else if (_state == VALUE) + return _valueDepth; + else + return _next.depth() + 2; + } + + State next(int ch) + { + switch (_state) { + case TYPE: + return nextObject(ch); + + case VALUE: + if (ch == 'Z') { + if (_count > 0) + println(); + + return _next; + } + else { + _valueDepth = _next.depth() + 2; + println(); + printObject(_count++ + ": "); + _valueDepth = _column; + _isObject = false; + + return nextObject(ch); + } + + default: + throw new IllegalStateException(); + } + } + } + + class CompactListState extends State { + private static final int TYPE = 0; + private static final int LENGTH = 1; + private static final int VALUE = 2; + + private int _refId; + + private boolean _isTyped; + private boolean _isLength; + + private int _state; + private boolean _hasData; + private int _length; + private int _count; + private int _valueDepth; + + CompactListState(State next, int refId, boolean isTyped) + { + super(next); + + _isTyped = isTyped; + _refId = refId; + + if (isTyped) + _state = TYPE; + else + _state = LENGTH; + } + + CompactListState(State next, int refId, boolean isTyped, int length) + { + super(next); + + _isTyped = isTyped; + _refId = refId; + _length = length; + + _isLength = true; + + if (isTyped) + _state = TYPE; + else { + printObject("list (#" + _refId + ")"); + + _state = VALUE; + } + } + + @Override + boolean isShift(Object value) + { + return _state == TYPE || _state == LENGTH; + } + + @Override + State shift(Object object) + { + if (_state == TYPE) { + Object type = object; + + if (object instanceof Integer) { + int index = (Integer) object; + + if (index >= 0 && index < _typeDefList.size()) + type = _typeDefList.get(index); + else + type = "type-unknown(" + index + ")"; + } + else if (object instanceof String) + _typeDefList.add((String) object); + + printObject("list " + type + " (#" + _refId + ")"); + + if (_isLength) { + _state = VALUE; + + if (_length == 0) + return _next; + } + else + _state = LENGTH; + + return this; + } + else if (_state == LENGTH) { + _length = (Integer) object; + + if (! _isTyped) + printObject("list (#" + _refId + ")"); + + _state = VALUE; + + if (_length == 0) + return _next; + else + return this; + } + else + return this; + } + + @Override + int depth() + { + if (_state <= LENGTH) + return _next.depth(); + else if (_state == VALUE) + return _valueDepth; + else + return _next.depth() + 2; + } + + State next(int ch) + { + switch (_state) { + case TYPE: + return nextObject(ch); + + case LENGTH: + return nextObject(ch); + + case VALUE: + if (_length <= _count) + return _next.next(ch); + else { + _valueDepth = _next.depth() + 2; + println(); + printObject(_count++ + ": "); + _valueDepth = _column; + _isObject = false; + + return nextObject(ch); + } + + default: + throw new IllegalStateException(); + } + } + } + + class Hessian2State extends State { + private static final int MAJOR = 0; + private static final int MINOR = 1; + + private int _state; + private int _major; + private int _minor; + + Hessian2State(State next) + { + super(next); + } + + int depth() + { + return _next.depth() + 2; + } + + State next(int ch) + { + switch (_state) { + case MAJOR: + _major = ch; + _state = MINOR; + return this; + + case MINOR: + _minor = ch; + println(-2, "hessian " + _major + "." + _minor); + return _next; + + default: + throw new IllegalStateException(); + } + } + } + + class CallState extends State { + private static final int MAJOR = 0; + private static final int MINOR = 1; + private static final int HEADER = 2; + private static final int METHOD = 3; + private static final int VALUE = 4; + private static final int ARG = 5; + + private int _state; + private int _major; + private int _minor; + + CallState(State next) + { + super(next); + } + + int depth() + { + return _next.depth() + 2; + } + + State next(int ch) + { + switch (_state) { + case MAJOR: + _major = ch; + _state = MINOR; + return this; + + case MINOR: + _minor = ch; + _state = HEADER; + println(-2, "call " + _major + "." + _minor); + return this; + + case HEADER: + if (ch == 'H') { + println(); + print("header "); + _isObject = false; + _state = VALUE; + return new StringState(this, 'H', true); + } + else if (ch == 'm') { + println(); + print("method "); + _isObject = false; + _state = ARG; + return new StringState(this, 'm', true); + } + else { + println((char) ch + ": unexpected char"); + return popStack(); + } + + case VALUE: + print(" => "); + _isObject = false; + _state = HEADER; + return nextObject(ch); + + case ARG: + if (ch == 'Z') + return _next; + else + return nextObject(ch); + + default: + throw new IllegalStateException(); + } + } + } + + class Call2State extends State { + private static final int METHOD = 0; + private static final int COUNT = 1; + private static final int ARG = 2; + + private int _state = METHOD; + private int _i; + private int _count; + + Call2State(State next) + { + super(next); + } + + int depth() + { + return _next.depth() + 5; + } + + @Override + boolean isShift(Object value) + { + return _state != ARG; + } + + @Override + State shift(Object object) + { + if (_state == METHOD) { + println(-5, "Call " + object); + + _state = COUNT; + return this; + } + else if (_state == COUNT) { + Integer count = (Integer) object; + + _count = count; + + _state = ARG; + + if (_count == 0) + return _next; + else + return this; + } + else + return this; + } + + @Override + State next(int ch) + { + switch (_state) { + case COUNT: + return nextObject(ch); + + case METHOD: + return nextObject(ch); + + case ARG: + if (_count <= _i) + return _next.next(ch); + else { + println(); + print(-3, _i++ + ": "); + + return nextObject(ch); + } + + default: + throw new IllegalStateException(); + } + } + } + + class ReplyState extends State { + private static final int MAJOR = 0; + private static final int MINOR = 1; + private static final int HEADER = 2; + private static final int VALUE = 3; + private static final int END = 4; + + private int _state; + private int _major; + private int _minor; + + ReplyState(State next) + { + _next = next; + } + + int depth() + { + return _next.depth() + 2; + } + + State next(int ch) + { + switch (_state) { + case MAJOR: + if (ch == 't' || ch == 'S') + return new RemoteState(this).next(ch); + + _major = ch; + _state = MINOR; + return this; + + case MINOR: + _minor = ch; + _state = HEADER; + println(-2, "reply " + _major + "." + _minor); + return this; + + case HEADER: + if (ch == 'H') { + _state = VALUE; + return new StringState(this, 'H', true); + } + else if (ch == 'f') { + print("fault "); + _isObject = false; + _state = END; + return new MapState(this, 0); + } + else { + _state = END; + return nextObject(ch); + } + + case VALUE: + _state = HEADER; + return nextObject(ch); + + case END: + println(); + if (ch == 'Z') { + return _next; + } + else + return _next.next(ch); + + default: + throw new IllegalStateException(); + } + } + } + + class Reply2State extends State { + Reply2State(State next) + { + super(next); + + println(-2, "Reply"); + } + + int depth() + { + return _next.depth() + 2; + } + + @Override + State next(int ch) + { + return nextObject(ch); + } + } + + class Fault2State extends State { + Fault2State(State next) + { + super(next); + + println(-2, "Fault"); + } + + int depth() + { + return _next.depth() + 2; + } + + @Override + State next(int ch) + { + return nextObject(ch); + } + } + + class IndirectState extends State { + IndirectState(State next) + { + super(next); + } + + boolean isShift(Object object) + { + return _next.isShift(object); + } + + State shift(Object object) + { + return _next.shift(object); + } + + State next(int ch) + { + return nextObject(ch); + } + } + + class RemoteState extends State { + private static final int TYPE = 0; + private static final int VALUE = 1; + private static final int END = 2; + + private int _state; + private int _major; + private int _minor; + + RemoteState(State next) + { + super(next); + } + + State next(int ch) + { + switch (_state) { + case TYPE: + println(-1, "remote"); + if (ch == 't') { + _state = VALUE; + return new StringState(this, 't', false); + } + else { + _state = END; + return nextObject(ch); + } + + case VALUE: + _state = END; + return _next.nextObject(ch); + + case END: + return _next.next(ch); + + default: + throw new IllegalStateException(); + } + } + } + + class StreamingState extends State { + private int _digit; + private int _length; + private boolean _isLast; + private boolean _isFirst = true; + + private State _childState; + + StreamingState(State next, boolean isLast) + { + super(next); + + _isLast = isLast; + _childState = new InitialState(); + } + + State next(int ch) + { + if (_digit < 2) { + _length = 256 * _length + ch; + _digit++; + + if (_digit == 2 && _length == 0 && _isLast) { + _refId = 0; + return _next; + } + else { + if (_digit == 2) + println(-1, "packet-start(" + _length + ")"); + + return this; + } + } + else if (_length == 0) { + _isLast = (ch == 'P'); + _digit = 0; + + return this; + } + + _childState = _childState.next(ch); + + _length--; + + if (_length == 0 && _isLast) { + println(-1, ""); + println(-1, "packet-end"); + _refId = 0; + return _next; + } + else + return this; + } + } + + static class ObjectDef { + private String _type; + private ArrayList _fields; + + ObjectDef(String type, ArrayList fields) + { + _type = type; + _fields = fields; + } + + String getType() + { + return _type; + } + + ArrayList getFields() + { + return _fields; + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianEnvelope.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianEnvelope.java new file mode 100644 index 000000000000..626548f4df4f --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianEnvelope.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.*; + +/** + * Factory class for wrapping and unwrapping hessian streams. + */ +abstract public class HessianEnvelope { + /** + * Wrap the Hessian output stream in an envelope. + */ + abstract public Hessian2Output wrap(Hessian2Output out) + throws IOException; + + /** + * Unwrap the Hessian input stream with this envelope. It is an + * error if the actual envelope does not match the expected envelope + * class. + */ + abstract public Hessian2Input unwrap(Hessian2Input in) + throws IOException; + + /** + * Unwrap the envelope after having read the envelope code ('E') and + * the envelope method. Called by the EnvelopeFactory for dynamic + * reading of the envelopes. + */ + abstract public Hessian2Input unwrapHeaders(Hessian2Input in) + throws IOException; +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianFieldException.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianFieldException.java new file mode 100644 index 000000000000..72dcd62f804d --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianFieldException.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; + +/** + * Exception during field reading. + */ +public class HessianFieldException extends HessianProtocolException { + /** + * Zero-arg constructor. + */ + public HessianFieldException() + { + } + + /** + * Create the exception. + */ + public HessianFieldException(String message) + { + super(message); + } + + /** + * Create the exception. + */ + public HessianFieldException(String message, Throwable cause) + { + super(message, cause); + } + + /** + * Create the exception. + */ + public HessianFieldException(Throwable cause) + { + super(cause); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianHandle.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianHandle.java new file mode 100644 index 000000000000..3103a871f761 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianHandle.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +/** + * Marks a type as a handle + */ +public interface HessianHandle { +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianInput.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianInput.java new file mode 100644 index 000000000000..363222ef69ba --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianInput.java @@ -0,0 +1,1700 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; + +/** + * Input stream for Hessian requests. + * + *

HessianInput is unbuffered, so any client needs to provide + * its own buffering. + * + *

+ * InputStream is = ...; // from http connection
+ * HessianInput in = new HessianInput(is);
+ * String value;
+ *
+ * in.startReply();         // read reply header
+ * value = in.readString(); // read string value
+ * in.completeReply();      // read reply footer
+ * 
+ */ +public class HessianInput extends AbstractHessianInput { + private static int END_OF_DATA = -2; + + private static Field _detailMessageField; + + // factory for deserializing objects in the input stream + protected SerializerFactory _serializerFactory; + + protected ArrayList _refs; + + // the underlying input stream + private InputStream _is; + // a peek character + protected int _peek = -1; + + // the method for a call + private String _method; + + private Reader _chunkReader; + private InputStream _chunkInputStream; + + private Throwable _replyFault; + + private StringBuffer _sbuf = new StringBuffer(); + + // true if this is the last chunk + private boolean _isLastChunk; + // the chunk length + private int _chunkLength; + + /** + * Creates an uninitialized Hessian input stream. + */ + public HessianInput() + { + } + + /** + * Creates a new Hessian input stream, initialized with an + * underlying input stream. + * + * @param is the underlying input stream. + */ + public HessianInput(InputStream is) + { + init(is); + } + + /** + * Sets the serializer factory. + */ + public void setSerializerFactory(SerializerFactory factory) + { + _serializerFactory = factory; + } + + /** + * Gets the serializer factory. + */ + public SerializerFactory getSerializerFactory() + { + return _serializerFactory; + } + + /** + * Initialize the hessian stream with the underlying input stream. + */ + public void init(InputStream is) + { + _is = is; + _method = null; + _isLastChunk = true; + _chunkLength = 0; + _peek = -1; + _refs = null; + _replyFault = null; + + if (_serializerFactory == null) + _serializerFactory = new SerializerFactory(); + } + + /** + * Returns the calls method + */ + public String getMethod() + { + return _method; + } + + /** + * Returns any reply fault. + */ + public Throwable getReplyFault() + { + return _replyFault; + } + + /** + * Starts reading the call + * + *
+   * c major minor
+   * 
+ */ + public int readCall() + throws IOException + { + int tag = read(); + + if (tag != 'c') + throw error("expected hessian call ('c') at " + codeName(tag)); + + int major = read(); + int minor = read(); + + return (major << 16) + minor; + } + + /** + * For backward compatibility with HessianSkeleton + */ + public void skipOptionalCall() + throws IOException + { + int tag = read(); + + if (tag == 'c') { + read(); + read(); + } + else + _peek = tag; + } + + /** + * Starts reading the call + * + *

A successful completion will have a single value: + * + *

+   * m b16 b8 method
+   * 
+ */ + public String readMethod() + throws IOException + { + int tag = read(); + + if (tag != 'm') + throw error("expected hessian method ('m') at " + codeName(tag)); + int d1 = read(); + int d2 = read(); + + _isLastChunk = true; + _chunkLength = d1 * 256 + d2; + _sbuf.setLength(0); + int ch; + while ((ch = parseChar()) >= 0) + _sbuf.append((char) ch); + + _method = _sbuf.toString(); + + return _method; + } + + /** + * Starts reading the call, including the headers. + * + *

The call expects the following protocol data + * + *

+   * c major minor
+   * m b16 b8 method
+   * 
+ */ + public void startCall() + throws IOException + { + readCall(); + + while (readHeader() != null) { + readObject(); + } + + readMethod(); + } + + /** + * Completes reading the call + * + *

A successful completion will have a single value: + * + *

+   * z
+   * 
+ */ + public void completeCall() + throws IOException + { + int tag = read(); + + if (tag == 'z') { + } + else + throw error("expected end of call ('z') at " + codeName(tag) + ". Check method arguments and ensure method overloading is enabled if necessary"); + } + + /** + * Reads a reply as an object. + * If the reply has a fault, throws the exception. + */ + public Object readReply(Class expectedClass) + throws Throwable + { + int tag = read(); + + if (tag != 'r') + error("expected hessian reply at " + codeName(tag)); + + int major = read(); + int minor = read(); + + tag = read(); + if (tag == 'f') + throw prepareFault(); + else { + _peek = tag; + + Object value = readObject(expectedClass); + + completeValueReply(); + + return value; + } + } + + /** + * Starts reading the reply + * + *

A successful completion will have a single value: + * + *

+   * r
+   * 
+ */ + public void startReply() + throws Throwable + { + int tag = read(); + + if (tag != 'r') + error("expected hessian reply at " + codeName(tag)); + + int major = read(); + int minor = read(); + + tag = read(); + if (tag == 'f') + throw prepareFault(); + else + _peek = tag; + } + + /** + * Prepares the fault. + */ + private Throwable prepareFault() + throws IOException + { + HashMap fault = readFault(); + + Object detail = fault.get("detail"); + String message = (String) fault.get("message"); + + if (detail instanceof Throwable) { + _replyFault = (Throwable) detail; + + if (message != null && _detailMessageField != null) { + try { + _detailMessageField.set(_replyFault, message); + } catch (Throwable e) { + } + } + + return _replyFault; + } + + else { + String code = (String) fault.get("code"); + + _replyFault = new HessianServiceException(message, code, detail); + + return _replyFault; + } + } + + /** + * Completes reading the call + * + *

A successful completion will have a single value: + * + *

+   * z
+   * 
+ */ + public void completeReply() + throws IOException + { + int tag = read(); + + if (tag != 'z') + error("expected end of reply at " + codeName(tag)); + } + + /** + * Completes reading the call + * + *

A successful completion will have a single value: + * + *

+   * z
+   * 
+ */ + public void completeValueReply() + throws IOException + { + int tag = read(); + + if (tag != 'z') + error("expected end of reply at " + codeName(tag)); + } + + /** + * Reads a header, returning null if there are no headers. + * + *
+   * H b16 b8 value
+   * 
+ */ + public String readHeader() + throws IOException + { + int tag = read(); + + if (tag == 'H') { + _isLastChunk = true; + _chunkLength = (read() << 8) + read(); + + _sbuf.setLength(0); + int ch; + while ((ch = parseChar()) >= 0) + _sbuf.append((char) ch); + + return _sbuf.toString(); + } + + _peek = tag; + + return null; + } + + /** + * Reads a null + * + *
+   * N
+   * 
+ */ + public void readNull() + throws IOException + { + int tag = read(); + + switch (tag) { + case 'N': return; + + default: + throw expect("null", tag); + } + } + + /** + * Reads a boolean + * + *
+   * T
+   * F
+   * 
+ */ + public boolean readBoolean() + throws IOException + { + int tag = read(); + + switch (tag) { + case 'T': return true; + case 'F': return false; + case 'I': return parseInt() == 0; + case 'L': return parseLong() == 0; + case 'D': return parseDouble() == 0.0; + case 'N': return false; + + default: + throw expect("boolean", tag); + } + } + + /** + * Reads a byte + * + *
+   * I b32 b24 b16 b8
+   * 
+ */ + /* + public byte readByte() + throws IOException + { + return (byte) readInt(); + } + */ + + /** + * Reads a short + * + *
+   * I b32 b24 b16 b8
+   * 
+ */ + public short readShort() + throws IOException + { + return (short) readInt(); + } + + /** + * Reads an integer + * + *
+   * I b32 b24 b16 b8
+   * 
+ */ + public int readInt() + throws IOException + { + int tag = read(); + + switch (tag) { + case 'T': return 1; + case 'F': return 0; + case 'I': return parseInt(); + case 'L': return (int) parseLong(); + case 'D': return (int) parseDouble(); + + default: + throw expect("int", tag); + } + } + + /** + * Reads a long + * + *
+   * L b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ */ + public long readLong() + throws IOException + { + int tag = read(); + + switch (tag) { + case 'T': return 1; + case 'F': return 0; + case 'I': return parseInt(); + case 'L': return parseLong(); + case 'D': return (long) parseDouble(); + + default: + throw expect("long", tag); + } + } + + /** + * Reads a float + * + *
+   * D b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ */ + public float readFloat() + throws IOException + { + return (float) readDouble(); + } + + /** + * Reads a double + * + *
+   * D b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ */ + public double readDouble() + throws IOException + { + int tag = read(); + + switch (tag) { + case 'T': return 1; + case 'F': return 0; + case 'I': return parseInt(); + case 'L': return (double) parseLong(); + case 'D': return parseDouble(); + + default: + throw expect("long", tag); + } + } + + /** + * Reads a date. + * + *
+   * T b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ */ + public long readUTCDate() + throws IOException + { + int tag = read(); + + if (tag != 'd') + throw error("expected date at " + codeName(tag)); + + long b64 = read(); + long b56 = read(); + long b48 = read(); + long b40 = read(); + long b32 = read(); + long b24 = read(); + long b16 = read(); + long b8 = read(); + + return ((b64 << 56) + + (b56 << 48) + + (b48 << 40) + + (b40 << 32) + + (b32 << 24) + + (b24 << 16) + + (b16 << 8) + + b8); + } + + /** + * Reads a byte from the stream. + */ + public int readChar() + throws IOException + { + if (_chunkLength > 0) { + _chunkLength--; + if (_chunkLength == 0 && _isLastChunk) + _chunkLength = END_OF_DATA; + + int ch = parseUTF8Char(); + return ch; + } + else if (_chunkLength == END_OF_DATA) { + _chunkLength = 0; + return -1; + } + + int tag = read(); + + switch (tag) { + case 'N': + return -1; + + case 'S': + case 's': + case 'X': + case 'x': + _isLastChunk = tag == 'S' || tag == 'X'; + _chunkLength = (read() << 8) + read(); + + _chunkLength--; + int value = parseUTF8Char(); + + // special code so successive read byte won't + // be read as a single object. + if (_chunkLength == 0 && _isLastChunk) + _chunkLength = END_OF_DATA; + + return value; + + default: + throw new IOException("expected 'S' at " + (char) tag); + } + } + + /** + * Reads a byte array from the stream. + */ + public int readString(char []buffer, int offset, int length) + throws IOException + { + int readLength = 0; + + if (_chunkLength == END_OF_DATA) { + _chunkLength = 0; + return -1; + } + else if (_chunkLength == 0) { + int tag = read(); + + switch (tag) { + case 'N': + return -1; + + case 'S': + case 's': + case 'X': + case 'x': + _isLastChunk = tag == 'S' || tag == 'X'; + _chunkLength = (read() << 8) + read(); + break; + + default: + throw new IOException("expected 'S' at " + (char) tag); + } + } + + while (length > 0) { + if (_chunkLength > 0) { + buffer[offset++] = (char) parseUTF8Char(); + _chunkLength--; + length--; + readLength++; + } + else if (_isLastChunk) { + if (readLength == 0) + return -1; + else { + _chunkLength = END_OF_DATA; + return readLength; + } + } + else { + int tag = read(); + + switch (tag) { + case 'S': + case 's': + case 'X': + case 'x': + _isLastChunk = tag == 'S' || tag == 'X'; + _chunkLength = (read() << 8) + read(); + break; + + default: + throw new IOException("expected 'S' at " + (char) tag); + } + } + } + + if (readLength == 0) + return -1; + else if (_chunkLength > 0 || ! _isLastChunk) + return readLength; + else { + _chunkLength = END_OF_DATA; + return readLength; + } + } + + /** + * Reads a string + * + *
+   * S b16 b8 string value
+   * 
+ */ + public String readString() + throws IOException + { + int tag = read(); + + switch (tag) { + case 'N': + return null; + + case 'I': + return String.valueOf(parseInt()); + case 'L': + return String.valueOf(parseLong()); + case 'D': + return String.valueOf(parseDouble()); + + case 'S': + case 's': + case 'X': + case 'x': + _isLastChunk = tag == 'S' || tag == 'X'; + _chunkLength = (read() << 8) + read(); + + _sbuf.setLength(0); + int ch; + + while ((ch = parseChar()) >= 0) + _sbuf.append((char) ch); + + return _sbuf.toString(); + + default: + throw expect("string", tag); + } + } + + /** + * Reads an XML node. + * + *
+   * S b16 b8 string value
+   * 
+ */ + public org.w3c.dom.Node readNode() + throws IOException + { + int tag = read(); + + switch (tag) { + case 'N': + return null; + + case 'S': + case 's': + case 'X': + case 'x': + _isLastChunk = tag == 'S' || tag == 'X'; + _chunkLength = (read() << 8) + read(); + + throw error("Can't handle string in this context"); + + default: + throw expect("string", tag); + } + } + + /** + * Reads a byte array + * + *
+   * B b16 b8 data value
+   * 
+ */ + public byte []readBytes() + throws IOException + { + int tag = read(); + + switch (tag) { + case 'N': + return null; + + case 'B': + case 'b': + _isLastChunk = tag == 'B'; + _chunkLength = (read() << 8) + read(); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + int data; + while ((data = parseByte()) >= 0) + bos.write(data); + + return bos.toByteArray(); + + default: + throw expect("bytes", tag); + } + } + + /** + * Reads a byte from the stream. + */ + public int readByte() + throws IOException + { + if (_chunkLength > 0) { + _chunkLength--; + if (_chunkLength == 0 && _isLastChunk) + _chunkLength = END_OF_DATA; + + return read(); + } + else if (_chunkLength == END_OF_DATA) { + _chunkLength = 0; + return -1; + } + + int tag = read(); + + switch (tag) { + case 'N': + return -1; + + case 'B': + case 'b': + _isLastChunk = tag == 'B'; + _chunkLength = (read() << 8) + read(); + + int value = parseByte(); + + // special code so successive read byte won't + // be read as a single object. + if (_chunkLength == 0 && _isLastChunk) + _chunkLength = END_OF_DATA; + + return value; + + default: + throw new IOException("expected 'B' at " + (char) tag); + } + } + + /** + * Reads a byte array from the stream. + */ + public int readBytes(byte []buffer, int offset, int length) + throws IOException + { + int readLength = 0; + + if (_chunkLength == END_OF_DATA) { + _chunkLength = 0; + return -1; + } + else if (_chunkLength == 0) { + int tag = read(); + + switch (tag) { + case 'N': + return -1; + + case 'B': + case 'b': + _isLastChunk = tag == 'B'; + _chunkLength = (read() << 8) + read(); + break; + + default: + throw new IOException("expected 'B' at " + (char) tag); + } + } + + while (length > 0) { + if (_chunkLength > 0) { + buffer[offset++] = (byte) read(); + _chunkLength--; + length--; + readLength++; + } + else if (_isLastChunk) { + if (readLength == 0) + return -1; + else { + _chunkLength = END_OF_DATA; + return readLength; + } + } + else { + int tag = read(); + + switch (tag) { + case 'B': + case 'b': + _isLastChunk = tag == 'B'; + _chunkLength = (read() << 8) + read(); + break; + + default: + throw new IOException("expected 'B' at " + (char) tag); + } + } + } + + if (readLength == 0) + return -1; + else if (_chunkLength > 0 || ! _isLastChunk) + return readLength; + else { + _chunkLength = END_OF_DATA; + return readLength; + } + } + + /** + * Reads a fault. + */ + private HashMap readFault() + throws IOException + { + HashMap map = new HashMap(); + + int code = read(); + for (; code > 0 && code != 'z'; code = read()) { + _peek = code; + + Object key = readObject(); + Object value = readObject(); + + if (key != null && value != null) + map.put(key, value); + } + + if (code != 'z') + throw expect("fault", code); + + return map; + } + + /** + * Reads an object from the input stream with an expected type. + */ + public Object readObject(Class cl) + throws IOException + { + if (cl == null || cl == Object.class) + return readObject(); + + int tag = read(); + + switch (tag) { + case 'N': + return null; + + case 'M': + { + String type = readType(); + + // hessian/3386 + if ("".equals(type)) { + Deserializer reader; + reader = _serializerFactory.getDeserializer(cl); + + return reader.readMap(this); + } + else { + Deserializer reader; + reader = _serializerFactory.getObjectDeserializer(type,cl); + + return reader.readMap(this); + } + } + + case 'V': + { + String type = readType(); + int length = readLength(); + + Deserializer reader; + reader = _serializerFactory.getObjectDeserializer(type); + + if (cl != reader.getType() && cl.isAssignableFrom(reader.getType())) + return reader.readList(this, length); + + reader = _serializerFactory.getDeserializer(cl); + + Object v = reader.readList(this, length); + + return v; + } + + case 'R': + { + int ref = parseInt(); + + return _refs.get(ref); + } + + case 'r': + { + String type = readType(); + String url = readString(); + + return resolveRemote(type, url); + } + } + + _peek = tag; + + // hessian/332i vs hessian/3406 + //return readObject(); + + Object value = _serializerFactory.getDeserializer(cl).readObject(this); + + return value; + } + + /** + * Reads an arbitrary object from the input stream when the type + * is unknown. + */ + public Object readObject() + throws IOException + { + int tag = read(); + + switch (tag) { + case 'N': + return null; + + case 'T': + return Boolean.valueOf(true); + + case 'F': + return Boolean.valueOf(false); + + case 'I': + return Integer.valueOf(parseInt()); + + case 'L': + return Long.valueOf(parseLong()); + + case 'D': + return Double.valueOf(parseDouble()); + + case 'd': + return new Date(parseLong()); + + case 'x': + case 'X': { + _isLastChunk = tag == 'X'; + _chunkLength = (read() << 8) + read(); + + return parseXML(); + } + + case 's': + case 'S': { + _isLastChunk = tag == 'S'; + _chunkLength = (read() << 8) + read(); + + int data; + _sbuf.setLength(0); + + while ((data = parseChar()) >= 0) + _sbuf.append((char) data); + + return _sbuf.toString(); + } + + case 'b': + case 'B': { + _isLastChunk = tag == 'B'; + _chunkLength = (read() << 8) + read(); + + int data; + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + while ((data = parseByte()) >= 0) + bos.write(data); + + return bos.toByteArray(); + } + + case 'V': { + String type = readType(); + int length = readLength(); + + return _serializerFactory.readList(this, length, type); + } + + case 'M': { + String type = readType(); + + return _serializerFactory.readMap(this, type); + } + + case 'R': { + int ref = parseInt(); + + return _refs.get(ref); + } + + case 'r': { + String type = readType(); + String url = readString(); + + return resolveRemote(type, url); + } + + default: + throw error("unknown code for readObject at " + codeName(tag)); + } + } + + /** + * Reads a remote object. + */ + public Object readRemote() + throws IOException + { + String type = readType(); + String url = readString(); + + return resolveRemote(type, url); + } + + /** + * Reads a reference. + */ + public Object readRef() + throws IOException + { + return _refs.get(parseInt()); + } + + /** + * Reads the start of a list. + */ + public int readListStart() + throws IOException + { + return read(); + } + + /** + * Reads the start of a list. + */ + public int readMapStart() + throws IOException + { + return read(); + } + + /** + * Returns true if this is the end of a list or a map. + */ + public boolean isEnd() + throws IOException + { + int code = read(); + + _peek = code; + + return (code < 0 || code == 'z'); + } + + /** + * Reads the end byte. + */ + public void readEnd() + throws IOException + { + int code = read(); + + if (code != 'z') + throw error("unknown code at " + codeName(code)); + } + + /** + * Reads the end byte. + */ + public void readMapEnd() + throws IOException + { + int code = read(); + + if (code != 'z') + throw error("expected end of map ('z') at " + codeName(code)); + } + + /** + * Reads the end byte. + */ + public void readListEnd() + throws IOException + { + int code = read(); + + if (code != 'z') + throw error("expected end of list ('z') at " + codeName(code)); + } + + /** + * Adds a list/map reference. + */ + public int addRef(Object ref) + { + if (_refs == null) + _refs = new ArrayList(); + + _refs.add(ref); + + return _refs.size() - 1; + } + + /** + * Adds a list/map reference. + */ + public void setRef(int i, Object ref) + { + _refs.set(i, ref); + } + + /** + * Resets the references for streaming. + */ + public void resetReferences() + { + if (_refs != null) + _refs.clear(); + } + + /** + * Resolves a remote object. + */ + public Object resolveRemote(String type, String url) + throws IOException + { + HessianRemoteResolver resolver = getRemoteResolver(); + + if (resolver != null) + return resolver.lookup(type, url); + else + return new HessianRemote(type, url); + } + + /** + * Parses a type from the stream. + * + *
+   * t b16 b8
+   * 
+ */ + public String readType() + throws IOException + { + int code = read(); + + if (code != 't') { + _peek = code; + return ""; + } + + _isLastChunk = true; + _chunkLength = (read() << 8) + read(); + + _sbuf.setLength(0); + int ch; + while ((ch = parseChar()) >= 0) + _sbuf.append((char) ch); + + return _sbuf.toString(); + } + + /** + * Parses the length for an array + * + *
+   * l b32 b24 b16 b8
+   * 
+ */ + public int readLength() + throws IOException + { + int code = read(); + + if (code != 'l') { + _peek = code; + return -1; + } + + return parseInt(); + } + + /** + * Parses a 32-bit integer value from the stream. + * + *
+   * b32 b24 b16 b8
+   * 
+ */ + private int parseInt() + throws IOException + { + int b32 = read(); + int b24 = read(); + int b16 = read(); + int b8 = read(); + + return (b32 << 24) + (b24 << 16) + (b16 << 8) + b8; + } + + /** + * Parses a 64-bit long value from the stream. + * + *
+   * b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ */ + private long parseLong() + throws IOException + { + long b64 = read(); + long b56 = read(); + long b48 = read(); + long b40 = read(); + long b32 = read(); + long b24 = read(); + long b16 = read(); + long b8 = read(); + + return ((b64 << 56) + + (b56 << 48) + + (b48 << 40) + + (b40 << 32) + + (b32 << 24) + + (b24 << 16) + + (b16 << 8) + + b8); + } + + /** + * Parses a 64-bit double value from the stream. + * + *
+   * b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ */ + private double parseDouble() + throws IOException + { + long b64 = read(); + long b56 = read(); + long b48 = read(); + long b40 = read(); + long b32 = read(); + long b24 = read(); + long b16 = read(); + long b8 = read(); + + long bits = ((b64 << 56) + + (b56 << 48) + + (b48 << 40) + + (b40 << 32) + + (b32 << 24) + + (b24 << 16) + + (b16 << 8) + + b8); + + return Double.longBitsToDouble(bits); + } + + org.w3c.dom.Node parseXML() + throws IOException + { + throw new UnsupportedOperationException(); + } + + /** + * Reads a character from the underlying stream. + */ + private int parseChar() + throws IOException + { + while (_chunkLength <= 0) { + if (_isLastChunk) + return -1; + + int code = read(); + + switch (code) { + case 's': + case 'x': + _isLastChunk = false; + + _chunkLength = (read() << 8) + read(); + break; + + case 'S': + case 'X': + _isLastChunk = true; + + _chunkLength = (read() << 8) + read(); + break; + + default: + throw expect("string", code); + } + + } + + _chunkLength--; + + return parseUTF8Char(); + } + + /** + * Parses a single UTF8 character. + */ + private int parseUTF8Char() + throws IOException + { + int ch = read(); + + if (ch < 0x80) + return ch; + else if ((ch & 0xe0) == 0xc0) { + int ch1 = read(); + int v = ((ch & 0x1f) << 6) + (ch1 & 0x3f); + + return v; + } + else if ((ch & 0xf0) == 0xe0) { + int ch1 = read(); + int ch2 = read(); + int v = ((ch & 0x0f) << 12) + ((ch1 & 0x3f) << 6) + (ch2 & 0x3f); + + return v; + } + else + throw error("bad utf-8 encoding at " + codeName(ch)); + } + + /** + * Reads a byte from the underlying stream. + */ + private int parseByte() + throws IOException + { + while (_chunkLength <= 0) { + if (_isLastChunk) { + return -1; + } + + int code = read(); + + switch (code) { + case 'b': + _isLastChunk = false; + + _chunkLength = (read() << 8) + read(); + break; + + case 'B': + _isLastChunk = true; + + _chunkLength = (read() << 8) + read(); + break; + + default: + throw expect("byte[]", code); + } + } + + _chunkLength--; + + return read(); + } + + /** + * Reads bytes based on an input stream. + */ + public InputStream readInputStream() + throws IOException + { + int tag = read(); + + switch (tag) { + case 'N': + return null; + + case 'B': + case 'b': + _isLastChunk = tag == 'B'; + _chunkLength = (read() << 8) + read(); + break; + + default: + throw expect("inputStream", tag); + } + + return new InputStream() { + boolean _isClosed = false; + + public int read() + throws IOException + { + if (_isClosed || _is == null) + return -1; + + int ch = parseByte(); + if (ch < 0) + _isClosed = true; + + return ch; + } + + public int read(byte []buffer, int offset, int length) + throws IOException + { + if (_isClosed || _is == null) + return -1; + + int len = HessianInput.this.read(buffer, offset, length); + if (len < 0) + _isClosed = true; + + return len; + } + + public void close() + throws IOException + { + while (read() >= 0) { + } + + _isClosed = true; + } + }; + } + + /** + * Reads bytes from the underlying stream. + */ + int read(byte []buffer, int offset, int length) + throws IOException + { + int readLength = 0; + + while (length > 0) { + while (_chunkLength <= 0) { + if (_isLastChunk) + return readLength == 0 ? -1 : readLength; + + int code = read(); + + switch (code) { + case 'b': + _isLastChunk = false; + + _chunkLength = (read() << 8) + read(); + break; + + case 'B': + _isLastChunk = true; + + _chunkLength = (read() << 8) + read(); + break; + + default: + throw expect("byte[]", code); + } + } + + int sublen = _chunkLength; + if (length < sublen) + sublen = length; + + sublen = _is.read(buffer, offset, sublen); + offset += sublen; + readLength += sublen; + length -= sublen; + _chunkLength -= sublen; + } + + return readLength; + } + + final int read() + throws IOException + { + if (_peek >= 0) { + int value = _peek; + _peek = -1; + return value; + } + + int ch = _is.read(); + + return ch; + } + + public void close() + { + _is = null; + } + + public Reader getReader() + { + return null; + } + + protected IOException expect(String expect, int ch) + { + return error("expected " + expect + " at " + codeName(ch)); + } + + protected String codeName(int ch) + { + if (ch < 0) + return "end of file"; + else + return "0x" + Integer.toHexString(ch & 0xff) + " (" + (char) + ch + ")"; + } + + protected IOException error(String message) + { + if (_method != null) + return new HessianProtocolException(_method + ": " + message); + else + return new HessianProtocolException(message); + } + + static { + try { + _detailMessageField = Throwable.class.getDeclaredField("detailMessage"); + _detailMessageField.setAccessible(true); + } catch (Throwable e) { + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianInputFactory.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianInputFactory.java new file mode 100644 index 000000000000..d5a24d1fd1cf --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianInputFactory.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.util.logging.*; +import java.io.*; + +public class HessianInputFactory +{ + public static final Logger log + = Logger.getLogger(HessianInputFactory.class.getName()); + + private SerializerFactory _serializerFactory; + + public void setSerializerFactory(SerializerFactory factory) + { + _serializerFactory = factory; + } + + public SerializerFactory getSerializerFactory() + { + return _serializerFactory; + } + + public AbstractHessianInput open(InputStream is) + throws IOException + { + int code = is.read(); + + int major = is.read(); + int minor = is.read(); + + switch (code) { + case 'c': + case 'C': + case 'r': + case 'R': + if (major >= 2) { + AbstractHessianInput in = new Hessian2Input(is); + in.setSerializerFactory(_serializerFactory); + return in; + } + else { + AbstractHessianInput in = new HessianInput(is); + in.setSerializerFactory(_serializerFactory); + return in; + } + + default: + throw new IOException((char) code + " is an unknown Hessian message code."); + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianOutput.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianOutput.java new file mode 100644 index 000000000000..6807f3db0f5c --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianOutput.java @@ -0,0 +1,949 @@ +/* + * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.IdentityHashMap; + +/** + * Output stream for Hessian requests, compatible with microedition + * Java. It only uses classes and types available in JDK. + * + *

Since HessianOutput does not depend on any classes other than + * in the JDK, it can be extracted independently into a smaller package. + * + *

HessianOutput is unbuffered, so any client needs to provide + * its own buffering. + * + *

+ * OutputStream os = ...; // from http connection
+ * HessianOutput out = new HessianOutput(os);
+ * String value;
+ *
+ * out.startCall("hello");  // start hello call
+ * out.writeString("arg1"); // write a string argument
+ * out.completeCall();      // complete the call
+ * 
+ */ +public class HessianOutput extends AbstractHessianOutput { + // the output stream/ + protected OutputStream os; + // map of references + private IdentityHashMap _refs; + private int _version = 1; + + /** + * Creates a new Hessian output stream, initialized with an + * underlying output stream. + * + * @param os the underlying output stream. + */ + public HessianOutput(OutputStream os) + { + init(os); + } + + /** + * Creates an uninitialized Hessian output stream. + */ + public HessianOutput() + { + } + + /** + * Initializes the output + */ + public void init(OutputStream os) + { + this.os = os; + + _refs = null; + + if (_serializerFactory == null) + _serializerFactory = new SerializerFactory(); + } + + /** + * Sets the client's version. + */ + public void setVersion(int version) + { + _version = version; + } + + /** + * Writes a complete method call. + */ + public void call(String method, Object []args) + throws IOException + { + int length = args != null ? args.length : 0; + + startCall(method, length); + + for (int i = 0; i < length; i++) + writeObject(args[i]); + + completeCall(); + } + + /** + * Starts the method call. Clients would use startCall + * instead of call if they wanted finer control over + * writing the arguments, or needed to write headers. + * + *
+   * c major minor
+   * m b16 b8 method-name
+   * 
+ * + * @param method the method name to call. + */ + public void startCall(String method, int length) + throws IOException + { + os.write('c'); + os.write(_version); + os.write(0); + + os.write('m'); + int len = method.length(); + os.write(len >> 8); + os.write(len); + printString(method, 0, len); + } + + /** + * Writes the call tag. This would be followed by the + * headers and the method tag. + * + *
+   * c major minor
+   * 
+ * + * @param method the method name to call. + */ + public void startCall() + throws IOException + { + os.write('c'); + os.write(0); + os.write(1); + } + + /** + * Writes the method tag. + * + *
+   * m b16 b8 method-name
+   * 
+ * + * @param method the method name to call. + */ + public void writeMethod(String method) + throws IOException + { + os.write('m'); + int len = method.length(); + os.write(len >> 8); + os.write(len); + printString(method, 0, len); + } + + /** + * Completes. + * + *
+   * z
+   * 
+ */ + public void completeCall() + throws IOException + { + os.write('z'); + } + + /** + * Starts the reply + * + *

A successful completion will have a single value: + * + *

+   * r
+   * 
+ */ + public void startReply() + throws IOException + { + os.write('r'); + os.write(1); + os.write(0); + } + + /** + * Completes reading the reply + * + *

A successful completion will have a single value: + * + *

+   * z
+   * 
+ */ + public void completeReply() + throws IOException + { + os.write('z'); + } + + /** + * Writes a header name. The header value must immediately follow. + * + *
+   * H b16 b8 foo value
+   * 
+ */ + public void writeHeader(String name) + throws IOException + { + int len = name.length(); + + os.write('H'); + os.write(len >> 8); + os.write(len); + + printString(name); + } + + /** + * Writes a fault. The fault will be written + * as a descriptive string followed by an object: + * + *
+   * f
+   * <string>code
+   * <string>the fault code
+   *
+   * <string>message
+   * <string>the fault mesage
+   *
+   * <string>detail
+   * mt\x00\xnnjavax.ejb.FinderException
+   *     ...
+   * z
+   * z
+   * 
+ * + * @param code the fault code, a three digit + */ + public void writeFault(String code, String message, Object detail) + throws IOException + { + os.write('f'); + writeString("code"); + writeString(code); + + writeString("message"); + writeString(message); + + if (detail != null) { + writeString("detail"); + writeObject(detail); + } + os.write('z'); + } + + /** + * Writes any object to the output stream. + */ + public void writeObject(Object object) + throws IOException + { + if (object == null) { + writeNull(); + return; + } + + Serializer serializer; + + serializer = _serializerFactory.getSerializer(object.getClass()); + + serializer.writeObject(object, this); + } + + /** + * Writes the list header to the stream. List writers will call + * writeListBegin followed by the list contents and then + * call writeListEnd. + * + *
+   * V
+   * t b16 b8 type
+   * l b32 b24 b16 b8
+   * 
+ */ + public boolean writeListBegin(int length, String type) + throws IOException + { + os.write('V'); + + if (type != null) { + os.write('t'); + printLenString(type); + } + + if (length >= 0) { + os.write('l'); + os.write(length >> 24); + os.write(length >> 16); + os.write(length >> 8); + os.write(length); + } + + return true; + } + + /** + * Writes the tail of the list to the stream. + */ + public void writeListEnd() + throws IOException + { + os.write('z'); + } + + /** + * Writes the map header to the stream. Map writers will call + * writeMapBegin followed by the map contents and then + * call writeMapEnd. + * + *
+   * Mt b16 b8 ( )z
+   * 
+ */ + public void writeMapBegin(String type) + throws IOException + { + os.write('M'); + os.write('t'); + printLenString(type); + } + + /** + * Writes the tail of the map to the stream. + */ + public void writeMapEnd() + throws IOException + { + os.write('z'); + } + + /** + * Writes a remote object reference to the stream. The type is the + * type of the remote interface. + * + *
+   * 'r' 't' b16 b8 type url
+   * 
+ */ + public void writeRemote(String type, String url) + throws IOException + { + os.write('r'); + os.write('t'); + printLenString(type); + os.write('S'); + printLenString(url); + } + + /** + * Writes a boolean value to the stream. The boolean will be written + * with the following syntax: + * + *
+   * T
+   * F
+   * 
+ * + * @param value the boolean value to write. + */ + public void writeBoolean(boolean value) + throws IOException + { + if (value) + os.write('T'); + else + os.write('F'); + } + + /** + * Writes an integer value to the stream. The integer will be written + * with the following syntax: + * + *
+   * I b32 b24 b16 b8
+   * 
+ * + * @param value the integer value to write. + */ + public void writeInt(int value) + throws IOException + { + os.write('I'); + os.write(value >> 24); + os.write(value >> 16); + os.write(value >> 8); + os.write(value); + } + + /** + * Writes a long value to the stream. The long will be written + * with the following syntax: + * + *
+   * L b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ * + * @param value the long value to write. + */ + public void writeLong(long value) + throws IOException + { + os.write('L'); + os.write((byte) (value >> 56)); + os.write((byte) (value >> 48)); + os.write((byte) (value >> 40)); + os.write((byte) (value >> 32)); + os.write((byte) (value >> 24)); + os.write((byte) (value >> 16)); + os.write((byte) (value >> 8)); + os.write((byte) (value)); + } + + /** + * Writes a double value to the stream. The double will be written + * with the following syntax: + * + *
+   * D b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ * + * @param value the double value to write. + */ + public void writeDouble(double value) + throws IOException + { + long bits = Double.doubleToLongBits(value); + + os.write('D'); + os.write((byte) (bits >> 56)); + os.write((byte) (bits >> 48)); + os.write((byte) (bits >> 40)); + os.write((byte) (bits >> 32)); + os.write((byte) (bits >> 24)); + os.write((byte) (bits >> 16)); + os.write((byte) (bits >> 8)); + os.write((byte) (bits)); + } + + /** + * Writes a date to the stream. + * + *
+   * T  b64 b56 b48 b40 b32 b24 b16 b8
+   * 
+ * + * @param time the date in milliseconds from the epoch in UTC + */ + public void writeUTCDate(long time) + throws IOException + { + os.write('d'); + os.write((byte) (time >> 56)); + os.write((byte) (time >> 48)); + os.write((byte) (time >> 40)); + os.write((byte) (time >> 32)); + os.write((byte) (time >> 24)); + os.write((byte) (time >> 16)); + os.write((byte) (time >> 8)); + os.write((byte) (time)); + } + + /** + * Writes a null value to the stream. + * The null will be written with the following syntax + * + *
+   * N
+   * 
+ * + * @param value the string value to write. + */ + public void writeNull() + throws IOException + { + os.write('N'); + } + + /** + * Writes a string value to the stream using UTF-8 encoding. + * The string will be written with the following syntax: + * + *
+   * S b16 b8 string-value
+   * 
+ * + * If the value is null, it will be written as + * + *
+   * N
+   * 
+ * + * @param value the string value to write. + */ + public void writeString(String value) + throws IOException + { + if (value == null) { + os.write('N'); + } + else { + int length = value.length(); + int offset = 0; + + while (length > 0x8000) { + int sublen = 0x8000; + + // chunk can't end in high surrogate + char tail = value.charAt(offset + sublen - 1); + + if (0xd800 <= tail && tail <= 0xdbff) + sublen--; + + os.write('s'); + os.write(sublen >> 8); + os.write(sublen); + + printString(value, offset, sublen); + + length -= sublen; + offset += sublen; + } + + os.write('S'); + os.write(length >> 8); + os.write(length); + + printString(value, offset, length); + } + } + + /** + * Writes a string value to the stream using UTF-8 encoding. + * The string will be written with the following syntax: + * + *
+   * S b16 b8 string-value
+   * 
+ * + * If the value is null, it will be written as + * + *
+   * N
+   * 
+ * + * @param value the string value to write. + */ + public void writeString(char []buffer, int offset, int length) + throws IOException + { + if (buffer == null) { + os.write('N'); + } + else { + while (length > 0x8000) { + int sublen = 0x8000; + + // chunk can't end in high surrogate + char tail = buffer[offset + sublen - 1]; + + if (0xd800 <= tail && tail <= 0xdbff) + sublen--; + + os.write('s'); + os.write(sublen >> 8); + os.write(sublen); + + printString(buffer, offset, sublen); + + length -= sublen; + offset += sublen; + } + + os.write('S'); + os.write(length >> 8); + os.write(length); + + printString(buffer, offset, length); + } + } + + /** + * Writes a byte array to the stream. + * The array will be written with the following syntax: + * + *
+   * B b16 b18 bytes
+   * 
+ * + * If the value is null, it will be written as + * + *
+   * N
+   * 
+ * + * @param value the string value to write. + */ + public void writeBytes(byte []buffer) + throws IOException + { + if (buffer == null) + os.write('N'); + else + writeBytes(buffer, 0, buffer.length); + } + + /** + * Writes a byte array to the stream. + * The array will be written with the following syntax: + * + *
+   * B b16 b18 bytes
+   * 
+ * + * If the value is null, it will be written as + * + *
+   * N
+   * 
+ * + * @param value the string value to write. + */ + public void writeBytes(byte []buffer, int offset, int length) + throws IOException + { + if (buffer == null) { + os.write('N'); + } + else { + while (length > 0x8000) { + int sublen = 0x8000; + + os.write('b'); + os.write(sublen >> 8); + os.write(sublen); + + os.write(buffer, offset, sublen); + + length -= sublen; + offset += sublen; + } + + os.write('B'); + os.write(length >> 8); + os.write(length); + os.write(buffer, offset, length); + } + } + + /** + * Writes a byte buffer to the stream. + * + *
+   * 
+ */ + public void writeByteBufferStart() + throws IOException + { + } + + /** + * Writes a byte buffer to the stream. + * + *
+   * b b16 b18 bytes
+   * 
+ */ + public void writeByteBufferPart(byte []buffer, int offset, int length) + throws IOException + { + while (length > 0) { + int sublen = length; + + if (0x8000 < sublen) + sublen = 0x8000; + + os.write('b'); + os.write(sublen >> 8); + os.write(sublen); + + os.write(buffer, offset, sublen); + + length -= sublen; + offset += sublen; + } + } + + /** + * Writes a byte buffer to the stream. + * + *
+   * b b16 b18 bytes
+   * 
+ */ + public void writeByteBufferEnd(byte []buffer, int offset, int length) + throws IOException + { + writeBytes(buffer, offset, length); + } + + /** + * Writes a reference. + * + *
+   * R b32 b24 b16 b8
+   * 
+ * + * @param value the integer value to write. + */ + public void writeRef(int value) + throws IOException + { + os.write('R'); + os.write(value >> 24); + os.write(value >> 16); + os.write(value >> 8); + os.write(value); + } + + /** + * Writes a placeholder. + * + *
+   * P
+   * 
+ */ + public void writePlaceholder() + throws IOException + { + os.write('P'); + } + + /** + * If the object has already been written, just write its ref. + * + * @return true if we're writing a ref. + */ + public boolean addRef(Object object) + throws IOException + { + if (_refs == null) + _refs = new IdentityHashMap(); + + Integer ref = (Integer) _refs.get(object); + + if (ref != null) { + int value = ref.intValue(); + + writeRef(value); + return true; + } + else { + _refs.put(object, new Integer(_refs.size())); + + return false; + } + } + + /** + * Resets the references for streaming. + */ + public void resetReferences() + { + if (_refs != null) + _refs.clear(); + } + + /** + * Removes a reference. + */ + public boolean removeRef(Object obj) + throws IOException + { + if (_refs != null) { + _refs.remove(obj); + + return true; + } + else + return false; + } + + /** + * Replaces a reference from one object to another. + */ + public boolean replaceRef(Object oldRef, Object newRef) + throws IOException + { + Integer value = (Integer) _refs.remove(oldRef); + + if (value != null) { + _refs.put(newRef, value); + return true; + } + else + return false; + } + + /** + * Prints a string to the stream, encoded as UTF-8 with preceeding length + * + * @param v the string to print. + */ + public void printLenString(String v) + throws IOException + { + if (v == null) { + os.write(0); + os.write(0); + } + else { + int len = v.length(); + os.write(len >> 8); + os.write(len); + + printString(v, 0, len); + } + } + + /** + * Prints a string to the stream, encoded as UTF-8 + * + * @param v the string to print. + */ + public void printString(String v) + throws IOException + { + printString(v, 0, v.length()); + } + + /** + * Prints a string to the stream, encoded as UTF-8 + * + * @param v the string to print. + */ + public void printString(String v, int offset, int length) + throws IOException + { + for (int i = 0; i < length; i++) { + char ch = v.charAt(i + offset); + + if (ch < 0x80) + os.write(ch); + else if (ch < 0x800) { + os.write(0xc0 + ((ch >> 6) & 0x1f)); + os.write(0x80 + (ch & 0x3f)); + } + else { + os.write(0xe0 + ((ch >> 12) & 0xf)); + os.write(0x80 + ((ch >> 6) & 0x3f)); + os.write(0x80 + (ch & 0x3f)); + } + } + } + + /** + * Prints a string to the stream, encoded as UTF-8 + * + * @param v the string to print. + */ + public void printString(char []v, int offset, int length) + throws IOException + { + for (int i = 0; i < length; i++) { + char ch = v[i + offset]; + + if (ch < 0x80) + os.write(ch); + else if (ch < 0x800) { + os.write(0xc0 + ((ch >> 6) & 0x1f)); + os.write(0x80 + (ch & 0x3f)); + } + else { + os.write(0xe0 + ((ch >> 12) & 0xf)); + os.write(0x80 + ((ch >> 6) & 0x3f)); + os.write(0x80 + (ch & 0x3f)); + } + } + } + + public void flush() + throws IOException + { + if (this.os != null) + this.os.flush(); + } + + public void close() + throws IOException + { + if (this.os != null) + this.os.flush(); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianProtocolException.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianProtocolException.java new file mode 100644 index 000000000000..e3f023e3edbe --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianProtocolException.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; + +/** + * Exception for faults when the fault doesn't return a java exception. + * This exception is required for MicroHessianInput. + */ +public class HessianProtocolException extends IOException { + private Throwable rootCause; + + /** + * Zero-arg constructor. + */ + public HessianProtocolException() + { + } + + /** + * Create the exception. + */ + public HessianProtocolException(String message) + { + super(message); + } + + /** + * Create the exception. + */ + public HessianProtocolException(String message, Throwable rootCause) + { + super(message); + + this.rootCause = rootCause; + } + + /** + * Create the exception. + */ + public HessianProtocolException(Throwable rootCause) + { + super(String.valueOf(rootCause)); + + this.rootCause = rootCause; + } + + /** + * Returns the underlying cause. + */ + public Throwable getRootCause() + { + return rootCause; + } + + /** + * Returns the underlying cause. + */ + public Throwable getCause() + { + return getRootCause(); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianRemote.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianRemote.java new file mode 100644 index 000000000000..bef32aba9392 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianRemote.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +/** + * Encapsulates a remote address when no stub is available, e.g. for + * Java MicroEdition. + */ +public class HessianRemote { + private String type; + private String url; + + /** + * Creates a new Hessian remote object. + * + * @param type the remote stub interface + * @param url the remote url + */ + public HessianRemote(String type, String url) + { + this.type = type; + this.url = url; + } + + /** + * Creates an uninitialized Hessian remote. + */ + public HessianRemote() + { + } + + /** + * Returns the remote api class name. + */ + public String getType() + { + return type; + } + + /** + * Returns the remote URL. + */ + public String getURL() + { + return url; + } + + /** + * Sets the remote URL. + */ + public void setURL(String url) + { + this.url = url; + } + + /** + * Defines the hashcode. + */ + public int hashCode() + { + return url.hashCode(); + } + + /** + * Defines equality + */ + public boolean equals(Object obj) + { + if (! (obj instanceof HessianRemote)) + return false; + + HessianRemote remote = (HessianRemote) obj; + + return url.equals(remote.url); + } + + /** + * Readable version of the remote. + */ + public String toString() + { + return "[HessianRemote " + url + "]"; + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianRemoteObject.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianRemoteObject.java new file mode 100644 index 000000000000..d33f47de32bc --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianRemoteObject.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +/** + * Interface for any hessian remote object. + */ +public interface HessianRemoteObject { + public String getHessianType(); + public String getHessianURL(); +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianRemoteResolver.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianRemoteResolver.java new file mode 100644 index 000000000000..c14b0f1e1dc0 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianRemoteResolver.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; + +/** + * Looks up remote objects. The default just returns a HessianRemote object. + */ +public interface HessianRemoteResolver { + /** + * Looks up a proxy object. + */ + public Object lookup(String type, String url) + throws IOException; +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianSerializerInput.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianSerializerInput.java new file mode 100644 index 000000000000..9651f1353e88 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianSerializerInput.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.HashMap; + +/** + * Input stream for Hessian requests, deserializing objects using the + * java.io.Serialization protocol. + * + *

HessianSerializerInput is unbuffered, so any client needs to provide + * its own buffering. + * + *

Serialization

+ * + *
+ * InputStream is = new FileInputStream("test.xml");
+ * HessianOutput in = new HessianSerializerOutput(is);
+ *
+ * Object obj = in.readObject();
+ * is.close();
+ * 
+ * + *

Parsing a Hessian reply

+ * + *
+ * InputStream is = ...; // from http connection
+ * HessianInput in = new HessianSerializerInput(is);
+ * String value;
+ *
+ * in.startReply();         // read reply header
+ * value = in.readString(); // read string value
+ * in.completeReply();      // read reply footer
+ * 
+ */ +public class HessianSerializerInput extends HessianInput { + /** + * Creates a new Hessian input stream, initialized with an + * underlying input stream. + * + * @param is the underlying input stream. + */ + public HessianSerializerInput(InputStream is) + { + super(is); + } + + /** + * Creates an uninitialized Hessian input stream. + */ + public HessianSerializerInput() + { + } + + /** + * Reads an object from the input stream. cl is known not to be + * a Map. + */ + protected Object readObjectImpl(Class cl) + throws IOException + { + try { + Object obj = cl.newInstance(); + + if (_refs == null) + _refs = new ArrayList(); + _refs.add(obj); + + HashMap fieldMap = getFieldMap(cl); + + int code = read(); + for (; code >= 0 && code != 'z'; code = read()) { + _peek = code; + + Object key = readObject(); + + Field field = (Field) fieldMap.get(key); + + if (field != null) { + Object value = readObject(field.getType()); + field.set(obj, value); + } + else { + Object value = readObject(); + } + } + + if (code != 'z') + throw expect("map", code); + + // if there's a readResolve method, call it + try { + Method method = cl.getMethod("readResolve", new Class[0]); + return method.invoke(obj, new Object[0]); + } catch (Exception e) { + } + + return obj; + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new IOExceptionWrapper(e); + } + } + + /** + * Creates a map of the classes fields. + */ + protected HashMap getFieldMap(Class cl) + { + HashMap fieldMap = new HashMap(); + + for (; cl != null; cl = cl.getSuperclass()) { + Field []fields = cl.getDeclaredFields(); + for (int i = 0; i < fields.length; i++) { + Field field = fields[i]; + + if (Modifier.isTransient(field.getModifiers()) || + Modifier.isStatic(field.getModifiers())) + continue; + + // XXX: could parameterize the handler to only deal with public + field.setAccessible(true); + + fieldMap.put(field.getName(), field); + } + } + + return fieldMap; + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianSerializerOutput.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianSerializerOutput.java new file mode 100644 index 000000000000..5b570b33b54f --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianSerializerOutput.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +/** + * Output stream for Hessian requests. + * + *

HessianOutput is unbuffered, so any client needs to provide + * its own buffering. + * + *

Serialization

+ * + *
+ * OutputStream os = new FileOutputStream("test.xml");
+ * HessianOutput out = new HessianSerializerOutput(os);
+ *
+ * out.writeObject(obj);
+ * os.close();
+ * 
+ * + *

Writing an RPC Call

+ * + *
+ * OutputStream os = ...; // from http connection
+ * HessianOutput out = new HessianSerializerOutput(os);
+ * String value;
+ *
+ * out.startCall("hello");  // start hello call
+ * out.writeString("arg1"); // write a string argument
+ * out.completeCall();      // complete the call
+ * 
+ */ +public class HessianSerializerOutput extends HessianOutput { + /** + * Creates a new Hessian output stream, initialized with an + * underlying output stream. + * + * @param os the underlying output stream. + */ + public HessianSerializerOutput(OutputStream os) + { + super(os); + } + + /** + * Creates an uninitialized Hessian output stream. + */ + public HessianSerializerOutput() + { + } + + /** + * Applications which override this can do custom serialization. + * + * @param object the object to write. + */ + public void writeObjectImpl(Object obj) + throws IOException + { + Class cl = obj.getClass(); + + try { + Method method = cl.getMethod("writeReplace", new Class[0]); + Object repl = method.invoke(obj, new Object[0]); + + writeObject(repl); + return; + } catch (Exception e) { + } + + try { + writeMapBegin(cl.getName()); + for (; cl != null; cl = cl.getSuperclass()) { + Field []fields = cl.getDeclaredFields(); + for (int i = 0; i < fields.length; i++) { + Field field = fields[i]; + + if (Modifier.isTransient(field.getModifiers()) || + Modifier.isStatic(field.getModifiers())) + continue; + + // XXX: could parameterize the handler to only deal with public + field.setAccessible(true); + + writeString(field.getName()); + writeObject(field.get(obj)); + } + } + writeMapEnd(); + } catch (IllegalAccessException e) { + throw new IOExceptionWrapper(e); + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianServiceException.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianServiceException.java new file mode 100644 index 000000000000..248e58f53234 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianServiceException.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +/** + * Exception for faults when the fault doesn't return a java exception. + * This exception is required for MicroHessianInput. + */ +public class HessianServiceException extends Exception { + private String code; + private Object detail; + + /** + * Zero-arg constructor. + */ + public HessianServiceException() + { + } + + /** + * Create the exception. + */ + public HessianServiceException(String message, String code, Object detail) + { + super(message); + this.code = code; + this.detail = detail; + } + + /** + * Returns the code. + */ + public String getCode() + { + return code; + } + + /** + * Returns the detail. + */ + public Object getDetail() + { + return detail; + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/IOExceptionWrapper.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/IOExceptionWrapper.java new file mode 100644 index 000000000000..bee3cf531e16 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/IOExceptionWrapper.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; + +/** + * Exception wrapper for IO. + */ +public class IOExceptionWrapper extends IOException { + private Throwable _cause; + + public IOExceptionWrapper(Throwable cause) + { + super(cause.toString()); + + _cause = cause; + } + + public IOExceptionWrapper(String msg, Throwable cause) + { + super(msg); + + _cause = cause; + } + + public Throwable getCause() + { + return _cause; + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/InputStreamDeserializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/InputStreamDeserializer.java new file mode 100644 index 000000000000..d4247945507d --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/InputStreamDeserializer.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Serializing a stream object. + */ +public class InputStreamDeserializer extends AbstractDeserializer { + public InputStreamDeserializer() + { + } + + public Object readObject(AbstractHessianInput in) + throws IOException + { + return in.readInputStream(); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/InputStreamSerializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/InputStreamSerializer.java new file mode 100644 index 000000000000..9ac9d66cec7b --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/InputStreamSerializer.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Serializing a stream object. + */ +public class InputStreamSerializer extends AbstractSerializer { + public InputStreamSerializer() + { + } + + public void writeObject(Object obj, AbstractHessianOutput out) + throws IOException + { + InputStream is = (InputStream) obj; + + if (is == null) + out.writeNull(); + else { + byte []buf = new byte[1024]; + int len; + + while ((len = is.read(buf, 0, buf.length)) > 0) { + out.writeByteBufferPart(buf, 0, len); + } + + out.writeByteBufferEnd(buf, 0, 0); + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/IteratorSerializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/IteratorSerializer.java new file mode 100644 index 000000000000..b3bff92379d1 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/IteratorSerializer.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.util.Iterator; + +/** + * Serializing a JDK 1.2 Iterator. + */ +public class IteratorSerializer extends AbstractSerializer { + private static IteratorSerializer _serializer; + + public static IteratorSerializer create() + { + if (_serializer == null) + _serializer = new IteratorSerializer(); + + return _serializer; + } + + public void writeObject(Object obj, AbstractHessianOutput out) + throws IOException + { + Iterator iter = (Iterator) obj; + + boolean hasEnd = out.writeListBegin(-1, null); + + while (iter.hasNext()) { + Object value = iter.next(); + + out.writeObject(value); + } + + if (hasEnd) + out.writeListEnd(); + } +} 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 new file mode 100644 index 000000000000..bd217c4e2bcc --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/JavaDeserializer.java @@ -0,0 +1,679 @@ +/* + * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.HashMap; + +import java.util.logging.*; + +/** + * Serializing an object for known object types. + */ +public class JavaDeserializer extends AbstractMapDeserializer { + private static final Logger log + = Logger.getLogger(JavaDeserializer.class.getName()); + + private Class _type; + private HashMap _fieldMap; + private Method _readResolve; + private Constructor _constructor; + private Object []_constructorArgs; + + public JavaDeserializer(Class cl) + { + _type = cl; + _fieldMap = getFieldMap(cl); + + _readResolve = getReadResolve(cl); + + if (_readResolve != null) { + _readResolve.setAccessible(true); + } + + Constructor []constructors = cl.getDeclaredConstructors(); + long bestCost = Long.MAX_VALUE; + + for (int i = 0; i < constructors.length; i++) { + Class []param = constructors[i].getParameterTypes(); + long cost = 0; + + for (int j = 0; j < param.length; j++) { + cost = 4 * cost; + + if (Object.class.equals(param[j])) + cost += 1; + else if (String.class.equals(param[j])) + cost += 2; + else if (int.class.equals(param[j])) + cost += 3; + else if (long.class.equals(param[j])) + cost += 4; + else if (param[j].isPrimitive()) + cost += 5; + else + cost += 6; + } + + if (cost < 0 || cost > (1 << 48)) + cost = 1 << 48; + + cost += (long) param.length << 48; + + if (cost < bestCost) { + _constructor = constructors[i]; + bestCost = cost; + } + } + + if (_constructor != null) { + _constructor.setAccessible(true); + Class []params = _constructor.getParameterTypes(); + _constructorArgs = new Object[params.length]; + for (int i = 0; i < params.length; i++) { + _constructorArgs[i] = getParamArg(params[i]); + } + } + } + + public Class getType() + { + return _type; + } + + public Object readMap(AbstractHessianInput in) + throws IOException + { + try { + Object obj = instantiate(); + + return readMap(in, obj); + } catch (IOException e) { + throw e; + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new IOExceptionWrapper(_type.getName() + ":" + e.getMessage(), e); + } + } + + public Object readObject(AbstractHessianInput in, String []fieldNames) + throws IOException + { + try { + Object obj = instantiate(); + + return readObject(in, obj, fieldNames); + } catch (IOException e) { + throw e; + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new IOExceptionWrapper(_type.getName() + ":" + e.getMessage(), e); + } + } + + /** + * Returns the readResolve method + */ + protected Method getReadResolve(Class cl) + { + for (; cl != null; cl = cl.getSuperclass()) { + Method []methods = cl.getDeclaredMethods(); + + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + + if (method.getName().equals("readResolve") && + method.getParameterTypes().length == 0) + return method; + } + } + + return null; + } + + public Object readMap(AbstractHessianInput in, Object obj) + throws IOException + { + try { + int ref = in.addRef(obj); + + while (! in.isEnd()) { + Object key = in.readObject(); + + FieldDeserializer deser = (FieldDeserializer) _fieldMap.get(key); + + if (deser != null) + deser.deserialize(in, obj); + else + in.readObject(); + } + + in.readMapEnd(); + + Object resolve = resolve(obj); + + if (obj != resolve) + in.setRef(ref, resolve); + + return resolve; + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new IOExceptionWrapper(e); + } + } + + public Object readObject(AbstractHessianInput in, + Object obj, + String []fieldNames) + throws IOException + { + try { + int ref = in.addRef(obj); + + for (int i = 0; i < fieldNames.length; i++) { + String name = fieldNames[i]; + + FieldDeserializer deser = (FieldDeserializer) _fieldMap.get(name); + + if (deser != null) + deser.deserialize(in, obj); + else + in.readObject(); + } + + Object resolve = resolve(obj); + + if (obj != resolve) + in.setRef(ref, resolve); + + return resolve; + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new IOExceptionWrapper(obj.getClass().getName() + ":" + e, e); + } + } + + private Object resolve(Object obj) + throws Exception + { + // if there's a readResolve method, call it + try { + if (_readResolve != null) + return _readResolve.invoke(obj, new Object[0]); + } catch (InvocationTargetException e) { + if (e.getTargetException() != null) + throw e; + } + + return obj; + } + + protected Object instantiate() + throws Exception + { + try { + if (_constructor != null) + return _constructor.newInstance(_constructorArgs); + else + return _type.newInstance(); + } catch (Exception e) { + throw new HessianProtocolException("'" + _type.getName() + "' could not be instantiated", e); + } + } + + /** + * Creates a map of the classes fields. + */ + protected HashMap getFieldMap(Class cl) + { + HashMap fieldMap = new HashMap(); + + for (; cl != null; cl = cl.getSuperclass()) { + Field []fields = cl.getDeclaredFields(); + for (int i = 0; i < fields.length; i++) { + Field field = fields[i]; + + if (Modifier.isTransient(field.getModifiers()) + || Modifier.isStatic(field.getModifiers())) + continue; + else if (fieldMap.get(field.getName()) != null) + continue; + + // XXX: could parameterize the handler to only deal with public + try { + field.setAccessible(true); + } catch (Throwable e) { + e.printStackTrace(); + } + + Class type = field.getType(); + FieldDeserializer deser; + + if (String.class.equals(type)) + deser = new StringFieldDeserializer(field); + else if (byte.class.equals(type)) { + deser = new ByteFieldDeserializer(field); + } + else if (short.class.equals(type)) { + deser = new ShortFieldDeserializer(field); + } + else if (int.class.equals(type)) { + deser = new IntFieldDeserializer(field); + } + else if (long.class.equals(type)) { + deser = new LongFieldDeserializer(field); + } + else if (float.class.equals(type)) { + deser = new FloatFieldDeserializer(field); + } + else if (double.class.equals(type)) { + deser = new DoubleFieldDeserializer(field); + } + else if (boolean.class.equals(type)) { + deser = new BooleanFieldDeserializer(field); + } + else if (java.sql.Date.class.equals(type)) { + deser = new SqlDateFieldDeserializer(field); + } + else if (java.sql.Timestamp.class.equals(type)) { + deser = new SqlTimestampFieldDeserializer(field); + } + else if (java.sql.Time.class.equals(type)) { + deser = new SqlTimeFieldDeserializer(field); + } + else { + deser = new ObjectFieldDeserializer(field); + } + + fieldMap.put(field.getName(), deser); + } + } + + return fieldMap; + } + + /** + * Creates a map of the classes fields. + */ + protected static Object getParamArg(Class cl) + { + if (! cl.isPrimitive()) + return null; + else if (boolean.class.equals(cl)) + return Boolean.FALSE; + else if (byte.class.equals(cl)) + return new Byte((byte) 0); + else if (short.class.equals(cl)) + return new Short((short) 0); + else if (char.class.equals(cl)) + return new Character((char) 0); + else if (int.class.equals(cl)) + return Integer.valueOf(0); + else if (long.class.equals(cl)) + return Long.valueOf(0); + else if (float.class.equals(cl)) + return Float.valueOf(0); + else if (double.class.equals(cl)) + return Double.valueOf(0); + else + throw new UnsupportedOperationException(); + } + + abstract static class FieldDeserializer { + abstract void deserialize(AbstractHessianInput in, Object obj) + throws IOException; + } + + static class ObjectFieldDeserializer extends FieldDeserializer { + private final Field _field; + + ObjectFieldDeserializer(Field field) + { + _field = field; + } + + void deserialize(AbstractHessianInput in, Object obj) + throws IOException + { + Object value = null; + + try { + value = in.readObject(_field.getType()); + + _field.set(obj, value); + } catch (Exception e) { + logDeserializeError(_field, obj, value, e); + } + } + } + + static class BooleanFieldDeserializer extends FieldDeserializer { + private final Field _field; + + BooleanFieldDeserializer(Field field) + { + _field = field; + } + + void deserialize(AbstractHessianInput in, Object obj) + throws IOException + { + boolean value = false; + + try { + value = in.readBoolean(); + + _field.setBoolean(obj, value); + } catch (Exception e) { + logDeserializeError(_field, obj, value, e); + } + } + } + + static class ByteFieldDeserializer extends FieldDeserializer { + private final Field _field; + + ByteFieldDeserializer(Field field) + { + _field = field; + } + + void deserialize(AbstractHessianInput in, Object obj) + throws IOException + { + int value = 0; + + try { + value = in.readInt(); + + _field.setByte(obj, (byte) value); + } catch (Exception e) { + logDeserializeError(_field, obj, value, e); + } + } + } + + static class ShortFieldDeserializer extends FieldDeserializer { + private final Field _field; + + ShortFieldDeserializer(Field field) + { + _field = field; + } + + void deserialize(AbstractHessianInput in, Object obj) + throws IOException + { + int value = 0; + + try { + value = in.readInt(); + + _field.setShort(obj, (short) value); + } catch (Exception e) { + logDeserializeError(_field, obj, value, e); + } + } + } + + static class IntFieldDeserializer extends FieldDeserializer { + private final Field _field; + + IntFieldDeserializer(Field field) + { + _field = field; + } + + void deserialize(AbstractHessianInput in, Object obj) + throws IOException + { + int value = 0; + + try { + value = in.readInt(); + + _field.setInt(obj, value); + } catch (Exception e) { + logDeserializeError(_field, obj, value, e); + } + } + } + + static class LongFieldDeserializer extends FieldDeserializer { + private final Field _field; + + LongFieldDeserializer(Field field) + { + _field = field; + } + + void deserialize(AbstractHessianInput in, Object obj) + throws IOException + { + long value = 0; + + try { + value = in.readLong(); + + _field.setLong(obj, value); + } catch (Exception e) { + logDeserializeError(_field, obj, value, e); + } + } + } + + static class FloatFieldDeserializer extends FieldDeserializer { + private final Field _field; + + FloatFieldDeserializer(Field field) + { + _field = field; + } + + void deserialize(AbstractHessianInput in, Object obj) + throws IOException + { + double value = 0; + + try { + value = in.readDouble(); + + _field.setFloat(obj, (float) value); + } catch (Exception e) { + logDeserializeError(_field, obj, value, e); + } + } + } + + static class DoubleFieldDeserializer extends FieldDeserializer { + private final Field _field; + + DoubleFieldDeserializer(Field field) + { + _field = field; + } + + void deserialize(AbstractHessianInput in, Object obj) + throws IOException + { + double value = 0; + + try { + value = in.readDouble(); + + _field.setDouble(obj, value); + } catch (Exception e) { + logDeserializeError(_field, obj, value, e); + } + } + } + + static class StringFieldDeserializer extends FieldDeserializer { + private final Field _field; + + StringFieldDeserializer(Field field) + { + _field = field; + } + + void deserialize(AbstractHessianInput in, Object obj) + throws IOException + { + String value = null; + + try { + value = in.readString(); + + _field.set(obj, value); + } catch (Exception e) { + logDeserializeError(_field, obj, value, e); + } + } + } + + static class SqlDateFieldDeserializer extends FieldDeserializer { + private final Field _field; + + SqlDateFieldDeserializer(Field field) + { + _field = field; + } + + void deserialize(AbstractHessianInput in, Object obj) + throws IOException + { + java.sql.Date value = null; + + try { + java.util.Date date = (java.util.Date) in.readObject(); + value = new java.sql.Date(date.getTime()); + + _field.set(obj, value); + } catch (Exception e) { + logDeserializeError(_field, obj, value, e); + } + } + } + + static class SqlTimestampFieldDeserializer extends FieldDeserializer { + private final Field _field; + + SqlTimestampFieldDeserializer(Field field) + { + _field = field; + } + + void deserialize(AbstractHessianInput in, Object obj) + throws IOException + { + java.sql.Timestamp value = null; + + try { + java.util.Date date = (java.util.Date) in.readObject(); + if (date != null) value = new java.sql.Timestamp(date.getTime()); + + _field.set(obj, value); + } catch (Exception e) { + logDeserializeError(_field, obj, value, e); + } + } + } + + static class SqlTimeFieldDeserializer extends FieldDeserializer { + private final Field _field; + + SqlTimeFieldDeserializer(Field field) + { + _field = field; + } + + void deserialize(AbstractHessianInput in, Object obj) + throws IOException + { + java.sql.Time value = null; + + try { + java.util.Date date = (java.util.Date) in.readObject(); + value = new java.sql.Time(date.getTime()); + + _field.set(obj, value); + } catch (Exception e) { + logDeserializeError(_field, obj, value, e); + } + } + } + + static void logDeserializeError(Field field, Object obj, Object value, + Throwable e) + throws IOException + { + String fieldName = (field.getDeclaringClass().getName() + + "." + field.getName()); + + if (e instanceof HessianFieldException) + throw (HessianFieldException) e; + else if (e instanceof IOException) + throw new HessianFieldException(fieldName + ": " + e.getMessage(), e); + + if (value != null) + throw new HessianFieldException(fieldName + ": " + value.getClass().getName() + " (" + value + ")" + + " cannot be assigned to '" + field.getType().getName() + "'", e); + else + throw new HessianFieldException(fieldName + ": " + field.getType().getName() + " cannot be assigned from null", e); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/JavaSerializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/JavaSerializer.java new file mode 100644 index 000000000000..0103358b2b33 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/JavaSerializer.java @@ -0,0 +1,434 @@ +/* + * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.io.Serializable; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Serializing an object for known object types. + */ +public class JavaSerializer extends AbstractSerializer +{ + private static final Logger log + = Logger.getLogger(JavaSerializer.class.getName()); + + private static Object []NULL_ARGS = new Object[0]; + + private Field []_fields; + private FieldSerializer []_fieldSerializers; + + private Object _writeReplaceFactory; + private Method _writeReplace; + + public JavaSerializer(Class cl, ClassLoader loader) + { + introspectWriteReplace(cl, loader); + + if (_writeReplace != null) + _writeReplace.setAccessible(true); + + ArrayList primitiveFields = new ArrayList(); + ArrayList compoundFields = new ArrayList(); + + for (; cl != null; cl = cl.getSuperclass()) { + Field []fields = cl.getDeclaredFields(); + for (int i = 0; i < fields.length; i++) { + Field field = fields[i]; + + if (Modifier.isTransient(field.getModifiers()) + || Modifier.isStatic(field.getModifiers())) + continue; + + // XXX: could parameterize the handler to only deal with public + field.setAccessible(true); + + if (field.getType().isPrimitive() + || (field.getType().getName().startsWith("java.lang.") + && ! field.getType().equals(Object.class))) + primitiveFields.add(field); + else + compoundFields.add(field); + } + } + + ArrayList fields = new ArrayList(); + fields.addAll(primitiveFields); + fields.addAll(compoundFields); + + _fields = new Field[fields.size()]; + fields.toArray(_fields); + + _fieldSerializers = new FieldSerializer[_fields.length]; + + for (int i = 0; i < _fields.length; i++) { + _fieldSerializers[i] = getFieldSerializer(_fields[i].getType()); + } + } + + private void introspectWriteReplace(Class cl, ClassLoader loader) + { + try { + String className = cl.getName() + "HessianSerializer"; + + Class serializerClass = Class.forName(className, false, loader); + + Object serializerObject = serializerClass.newInstance(); + + Method writeReplace = getWriteReplace(serializerClass, cl); + + if (writeReplace != null) { + _writeReplaceFactory = serializerObject; + _writeReplace = writeReplace; + + return; + } + } catch (ClassNotFoundException e) { + } catch (Exception e) { + log.log(Level.FINER, e.toString(), e); + } + + _writeReplace = getWriteReplace(cl); + } + + /** + * Returns the writeReplace method + */ + protected static Method getWriteReplace(Class cl) + { + for (; cl != null; cl = cl.getSuperclass()) { + Method []methods = cl.getDeclaredMethods(); + + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + + if (method.getName().equals("writeReplace") && + method.getParameterTypes().length == 0) + return method; + } + } + + return null; + } + + /** + * Returns the writeReplace method + */ + protected Method getWriteReplace(Class cl, Class param) + { + for (; cl != null; cl = cl.getSuperclass()) { + for (Method method : cl.getDeclaredMethods()) { + if (method.getName().equals("writeReplace") + && method.getParameterTypes().length == 1 + && param.equals(method.getParameterTypes()[0])) + return method; + } + } + + return null; + } + + public void writeObject(Object obj, AbstractHessianOutput out) + throws IOException + { + if (out.addRef(obj)) { + return; + } + + Class cl = obj.getClass(); + + try { + if (_writeReplace != null) { + Object repl; + + if (_writeReplaceFactory != null) + repl = _writeReplace.invoke(_writeReplaceFactory, obj); + else + repl = _writeReplace.invoke(obj); + + out.removeRef(obj); + + out.writeObject(repl); + + out.replaceRef(repl, obj); + + return; + } + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + // log.log(Level.FINE, e.toString(), e); + throw new RuntimeException(e); + } + + int ref = out.writeObjectBegin(cl.getName()); + + if (ref < -1) { + writeObject10(obj, out); + } + else { + if (ref == -1) { + writeDefinition20(out); + out.writeObjectBegin(cl.getName()); + } + + writeInstance(obj, out); + } + } + + private void writeObject10(Object obj, AbstractHessianOutput out) + throws IOException + { + for (int i = 0; i < _fields.length; i++) { + Field field = _fields[i]; + + out.writeString(field.getName()); + + _fieldSerializers[i].serialize(out, obj, field); + } + + out.writeMapEnd(); + } + + private void writeDefinition20(AbstractHessianOutput out) + throws IOException + { + out.writeClassFieldLength(_fields.length); + + for (int i = 0; i < _fields.length; i++) { + Field field = _fields[i]; + + out.writeString(field.getName()); + } + } + + public void writeInstance(Object obj, AbstractHessianOutput out) + throws IOException + { + for (int i = 0; i < _fields.length; i++) { + Field field = _fields[i]; + + _fieldSerializers[i].serialize(out, obj, field); + } + } + + private static FieldSerializer getFieldSerializer(Class type) + { + if (int.class.equals(type) + || byte.class.equals(type) + || short.class.equals(type) + || int.class.equals(type)) { + return IntFieldSerializer.SER; + } + else if (long.class.equals(type)) { + return LongFieldSerializer.SER; + } + else if (double.class.equals(type) || + float.class.equals(type)) { + return DoubleFieldSerializer.SER; + } + else if (boolean.class.equals(type)) { + return BooleanFieldSerializer.SER; + } + else if (String.class.equals(type)) { + return StringFieldSerializer.SER; + } + else if (java.util.Date.class.equals(type) + || java.sql.Date.class.equals(type) + || java.sql.Timestamp.class.equals(type) + || java.sql.Time.class.equals(type)) { + return DateFieldSerializer.SER; + } + else + return FieldSerializer.SER; + } + + static class FieldSerializer { + static final FieldSerializer SER = new FieldSerializer(); + + void serialize(AbstractHessianOutput out, Object obj, Field field) + throws IOException + { + Object value = null; + + try { + value = field.get(obj); + } catch (IllegalAccessException e) { + log.log(Level.FINE, e.toString(), e); + } + + try { + out.writeObject(value); + } catch (RuntimeException e) { + throw new RuntimeException(e.getMessage() + "\n Java field: " + field, + e); + } catch (IOException e) { + throw new IOExceptionWrapper(e.getMessage() + "\n Java field: " + field, + e); + } + } + } + + static class BooleanFieldSerializer extends FieldSerializer { + static final FieldSerializer SER = new BooleanFieldSerializer(); + + void serialize(AbstractHessianOutput out, Object obj, Field field) + throws IOException + { + boolean value = false; + + try { + value = field.getBoolean(obj); + } catch (IllegalAccessException e) { + log.log(Level.FINE, e.toString(), e); + } + + out.writeBoolean(value); + } + } + + static class IntFieldSerializer extends FieldSerializer { + static final FieldSerializer SER = new IntFieldSerializer(); + + void serialize(AbstractHessianOutput out, Object obj, Field field) + throws IOException + { + int value = 0; + + try { + value = field.getInt(obj); + } catch (IllegalAccessException e) { + log.log(Level.FINE, e.toString(), e); + } + + out.writeInt(value); + } + } + + static class LongFieldSerializer extends FieldSerializer { + static final FieldSerializer SER = new LongFieldSerializer(); + + void serialize(AbstractHessianOutput out, Object obj, Field field) + throws IOException + { + long value = 0; + + try { + value = field.getLong(obj); + } catch (IllegalAccessException e) { + log.log(Level.FINE, e.toString(), e); + } + + out.writeLong(value); + } + } + + static class DoubleFieldSerializer extends FieldSerializer { + static final FieldSerializer SER = new DoubleFieldSerializer(); + + void serialize(AbstractHessianOutput out, Object obj, Field field) + throws IOException + { + double value = 0; + + try { + value = field.getDouble(obj); + } catch (IllegalAccessException e) { + log.log(Level.FINE, e.toString(), e); + } + + out.writeDouble(value); + } + } + + static class StringFieldSerializer extends FieldSerializer { + static final FieldSerializer SER = new StringFieldSerializer(); + + void serialize(AbstractHessianOutput out, Object obj, Field field) + throws IOException + { + String value = null; + + try { + value = (String) field.get(obj); + } catch (IllegalAccessException e) { + log.log(Level.FINE, e.toString(), e); + } + + out.writeString(value); + } + } + + static class DateFieldSerializer extends FieldSerializer { + static final FieldSerializer SER = new DateFieldSerializer(); + + void serialize(AbstractHessianOutput out, Object obj, Field field) + throws IOException + { + java.util.Date value = null; + + try { + value = (java.util.Date) field.get(obj); + } catch (IllegalAccessException e) { + log.log(Level.FINE, e.toString(), e); + } + + if (value == null) + out.writeNull(); + else + out.writeUTCDate(value.getTime()); + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/LocaleHandle.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/LocaleHandle.java new file mode 100644 index 000000000000..21454cf6c8c9 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/LocaleHandle.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.util.Locale; + +/** + * Handle for a locale object. + */ +public class LocaleHandle implements java.io.Serializable, HessianHandle { + private String value; + + public LocaleHandle(String locale) + { + this.value = locale; + } + + private Object readResolve() + { + String s = this.value; + + if (s == null) + return null; + + int len = s.length(); + char ch = ' '; + + int i = 0; + for (; + i < len && ('a' <= (ch = s.charAt(i)) && ch <= 'z' + || 'A' <= ch && ch <= 'Z' + || '0' <= ch && ch <= '9'); + i++) { + } + + String language = s.substring(0, i); + String country = null; + String var = null; + + if (ch == '-' || ch == '_') { + int head = ++i; + + for (; + i < len && ('a' <= (ch = s.charAt(i)) && ch <= 'z' + || 'A' <= ch && ch <= 'Z' + || '0' <= ch && ch <= '9'); + i++) { + } + + country = s.substring(head, i); + } + + if (ch == '-' || ch == '_') { + int head = ++i; + + for (; + i < len && ('a' <= (ch = s.charAt(i)) && ch <= 'z' + || 'A' <= ch && ch <= 'Z' + || '0' <= ch && ch <= '9'); + i++) { + } + + var = s.substring(head, i); + } + + if (var != null) + return new Locale(language, country, var); + else if (country != null) + return new Locale(language, country); + else + return new Locale(language); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/LocaleSerializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/LocaleSerializer.java new file mode 100644 index 000000000000..367c98667167 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/LocaleSerializer.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.util.Locale; + +/** + * Serializing a locale. + */ +public class LocaleSerializer extends AbstractSerializer { + private static LocaleSerializer SERIALIZER = new LocaleSerializer(); + + public static LocaleSerializer create() + { + return SERIALIZER; + } + + public void writeObject(Object obj, AbstractHessianOutput out) + throws IOException + { + if (obj == null) + out.writeNull(); + else { + Locale locale = (Locale) obj; + + out.writeObject(new LocaleHandle(locale.toString())); + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/MapDeserializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/MapDeserializer.java new file mode 100644 index 000000000000..5c51d9a70761 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/MapDeserializer.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.util.*; +import java.lang.reflect.*; + +/** + * Deserializing a JDK 1.2 Map. + */ +public class MapDeserializer extends AbstractMapDeserializer { + private Class _type; + private Constructor _ctor; + + public MapDeserializer(Class type) + { + if (type == null) + type = HashMap.class; + + _type = type; + + Constructor []ctors = type.getConstructors(); + for (int i = 0; i < ctors.length; i++) { + if (ctors[i].getParameterTypes().length == 0) + _ctor = ctors[i]; + } + + if (_ctor == null) { + try { + _ctor = HashMap.class.getConstructor(new Class[0]); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + } + + public Class getType() + { + if (_type != null) + return _type; + else + return HashMap.class; + } + + public Object readMap(AbstractHessianInput in) + throws IOException + { + Map map; + + if (_type == null) + map = new HashMap(); + else if (_type.equals(Map.class)) + map = new HashMap(); + else if (_type.equals(SortedMap.class)) + map = new TreeMap(); + else { + try { + map = (Map) _ctor.newInstance(); + } catch (Exception e) { + throw new IOExceptionWrapper(e); + } + } + + in.addRef(map); + + while (! in.isEnd()) { + map.put(in.readObject(), in.readObject()); + } + + in.readEnd(); + + return map; + } + + @Override + public Object readObject(AbstractHessianInput in, + String []fieldNames) + throws IOException + { + Map map = createMap(); + + int ref = in.addRef(map); + + for (int i = 0; i < fieldNames.length; i++) { + String name = fieldNames[i]; + + map.put(name, in.readObject()); + } + + return map; + } + + private Map createMap() + throws IOException + { + + if (_type == null) + return new HashMap(); + else if (_type.equals(Map.class)) + return new HashMap(); + else if (_type.equals(SortedMap.class)) + return new TreeMap(); + else { + try { + return (Map) _ctor.newInstance(); + } catch (Exception e) { + throw new IOExceptionWrapper(e); + } + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/MapSerializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/MapSerializer.java new file mode 100644 index 000000000000..c166060ab29b --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/MapSerializer.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * Serializing a JDK 1.2 java.util.Map. + */ +public class MapSerializer extends AbstractSerializer { + private boolean _isSendJavaType = true; + + /** + * Set true if the java type of the collection should be sent. + */ + public void setSendJavaType(boolean sendJavaType) + { + _isSendJavaType = sendJavaType; + } + + /** + * Return true if the java type of the collection should be sent. + */ + public boolean getSendJavaType() + { + return _isSendJavaType; + } + + public void writeObject(Object obj, AbstractHessianOutput out) + throws IOException + { + if (out.addRef(obj)) + return; + + Map map = (Map) obj; + + Class cl = obj.getClass(); + + if (cl.equals(HashMap.class) + || ! _isSendJavaType + || ! (obj instanceof java.io.Serializable)) + out.writeMapBegin(null); + else + out.writeMapBegin(obj.getClass().getName()); + + Iterator iter = map.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry entry = (Map.Entry) iter.next(); + + out.writeObject(entry.getKey()); + out.writeObject(entry.getValue()); + } + out.writeMapEnd(); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ObjectDeserializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ObjectDeserializer.java new file mode 100644 index 000000000000..5f554d1a54a8 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ObjectDeserializer.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Date; + +/** + * Serializing an object for known object types. + */ +public class ObjectDeserializer extends AbstractDeserializer { + private Class _cl; + + public ObjectDeserializer(Class cl) + { + _cl = cl; + } + + public Class getType() + { + return _cl; + } + + public Object readObject(AbstractHessianInput in) + throws IOException + { + return in.readObject(); + } + + public Object readObject(AbstractHessianInput in, String []fieldNames) + throws IOException + { + throw new UnsupportedOperationException(String.valueOf(this)); + } + + public Object readList(AbstractHessianInput in, int length) + throws IOException + { + throw new UnsupportedOperationException(String.valueOf(this)); + } + + public Object readLengthList(AbstractHessianInput in, int length) + throws IOException + { + throw new UnsupportedOperationException(String.valueOf(this)); + } + + @Override + public String toString() + { + return getClass().getSimpleName() + "[" + _cl + "]"; + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/RemoteSerializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/RemoteSerializer.java new file mode 100644 index 000000000000..3d7e0d88d62e --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/RemoteSerializer.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; + +/** + * Serializing a remote object. + */ +public class RemoteSerializer extends AbstractSerializer { + public void writeObject(Object obj, AbstractHessianOutput out) + throws IOException + { + // XXX: needs to be handled as a separate class + throw new UnsupportedOperationException(getClass().getName()); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Serializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Serializer.java new file mode 100644 index 000000000000..67060d9a8f2b --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Serializer.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; + +/** + * Serializing an object. + */ +public interface Serializer { + public void writeObject(Object obj, AbstractHessianOutput out) + throws IOException; +} 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 new file mode 100644 index 000000000000..46a16fbceb8c --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/SerializerFactory.java @@ -0,0 +1,649 @@ +/* + * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.*; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.*; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.management.*; + +/** + * Factory for returning serialization methods. + */ +public class SerializerFactory extends AbstractSerializerFactory +{ + private static final Logger log + = Logger.getLogger(SerializerFactory.class.getName()); + + private static Deserializer OBJECT_DESERIALIZER + = new BasicDeserializer(BasicDeserializer.OBJECT); + + private static HashMap _staticSerializerMap; + private static HashMap _staticDeserializerMap; + private static HashMap _staticTypeMap; + + private ClassLoader _loader; + + protected Serializer _defaultSerializer; + + // Additional factories + protected ArrayList _factories = new ArrayList(); + + protected CollectionSerializer _collectionSerializer; + protected MapSerializer _mapSerializer; + + private Deserializer _hashMapDeserializer; + private Deserializer _arrayListDeserializer; + private HashMap _cachedSerializerMap; + private HashMap _cachedDeserializerMap; + private HashMap _cachedTypeDeserializerMap; + + private boolean _isAllowNonSerializable; + + public SerializerFactory() + { + this(Thread.currentThread().getContextClassLoader()); + } + + public SerializerFactory(ClassLoader loader) + { + _loader = loader; + } + + public ClassLoader getClassLoader() + { + return _loader; + } + + /** + * Set true if the collection serializer should send the java type. + */ + public void setSendCollectionType(boolean isSendType) + { + if (_collectionSerializer == null) + _collectionSerializer = new CollectionSerializer(); + + _collectionSerializer.setSendJavaType(isSendType); + + if (_mapSerializer == null) + _mapSerializer = new MapSerializer(); + + _mapSerializer.setSendJavaType(isSendType); + } + + /** + * Adds a factory. + */ + public void addFactory(AbstractSerializerFactory factory) + { + _factories.add(factory); + } + + /** + * If true, non-serializable objects are allowed. + */ + public void setAllowNonSerializable(boolean allow) + { + _isAllowNonSerializable = allow; + } + + /** + * If true, non-serializable objects are allowed. + */ + public boolean isAllowNonSerializable() + { + return _isAllowNonSerializable; + } + + /** + * Returns the serializer for a class. + * + * @param cl the class of the object that needs to be serialized. + * + * @return a serializer object for the serialization. + */ + public Serializer getSerializer(Class cl) + throws HessianProtocolException + { + Serializer serializer; + + serializer = (Serializer) _staticSerializerMap.get(cl); + if (serializer != null) + return serializer; + + if (_cachedSerializerMap != null) { + synchronized (_cachedSerializerMap) { + serializer = (Serializer) _cachedSerializerMap.get(cl); + } + + if (serializer != null) + return serializer; + } + + for (int i = 0; + serializer == null && _factories != null && i < _factories.size(); + i++) { + AbstractSerializerFactory factory; + + factory = (AbstractSerializerFactory) _factories.get(i); + + serializer = factory.getSerializer(cl); + } + + if (serializer != null) { + } + + else if (JavaSerializer.getWriteReplace(cl) != null) + serializer = new JavaSerializer(cl, _loader); + + else if (HessianRemoteObject.class.isAssignableFrom(cl)) + serializer = new RemoteSerializer(); + +// else if (BurlapRemoteObject.class.isAssignableFrom(cl)) +// serializer = new RemoteSerializer(); + + else if (Map.class.isAssignableFrom(cl)) { + if (_mapSerializer == null) + _mapSerializer = new MapSerializer(); + + serializer = _mapSerializer; + } + else if (Collection.class.isAssignableFrom(cl)) { + if (_collectionSerializer == null) { + _collectionSerializer = new CollectionSerializer(); + } + + serializer = _collectionSerializer; + } + + else if (cl.isArray()) + serializer = new ArraySerializer(); + + else if (Throwable.class.isAssignableFrom(cl)) + serializer = new ThrowableSerializer(cl, getClassLoader()); + + else if (InputStream.class.isAssignableFrom(cl)) + serializer = new InputStreamSerializer(); + + else if (Iterator.class.isAssignableFrom(cl)) + serializer = IteratorSerializer.create(); + + else if (Enumeration.class.isAssignableFrom(cl)) + serializer = EnumerationSerializer.create(); + + else if (Calendar.class.isAssignableFrom(cl)) + serializer = CalendarSerializer.create(); + + else if (Locale.class.isAssignableFrom(cl)) + serializer = LocaleSerializer.create(); + + else if (Enum.class.isAssignableFrom(cl)) + serializer = new EnumSerializer(cl); + + if (serializer == null) + serializer = getDefaultSerializer(cl); + + if (_cachedSerializerMap == null) + _cachedSerializerMap = new HashMap(8); + + synchronized (_cachedSerializerMap) { + _cachedSerializerMap.put(cl, serializer); + } + + return serializer; + } + + /** + * Returns the default serializer for a class that isn't matched + * directly. Application can override this method to produce + * bean-style serialization instead of field serialization. + * + * @param cl the class of the object that needs to be serialized. + * + * @return a serializer object for the serialization. + */ + protected Serializer getDefaultSerializer(Class cl) + { + if (_defaultSerializer != null) + return _defaultSerializer; + + if (! Serializable.class.isAssignableFrom(cl) + && ! _isAllowNonSerializable) { + throw new IllegalStateException("Serialized class " + cl.getName() + " must implement java.io.Serializable"); + } + + return new JavaSerializer(cl, _loader); + } + + /** + * Returns the deserializer for a class. + * + * @param cl the class of the object that needs to be deserialized. + * + * @return a deserializer object for the serialization. + */ + public Deserializer getDeserializer(Class cl) + throws HessianProtocolException + { + Deserializer deserializer; + + deserializer = (Deserializer) _staticDeserializerMap.get(cl); + if (deserializer != null) + return deserializer; + + if (_cachedDeserializerMap != null) { + synchronized (_cachedDeserializerMap) { + deserializer = (Deserializer) _cachedDeserializerMap.get(cl); + } + + if (deserializer != null) + return deserializer; + } + + + for (int i = 0; + deserializer == null && _factories != null && i < _factories.size(); + i++) { + AbstractSerializerFactory factory; + factory = (AbstractSerializerFactory) _factories.get(i); + + deserializer = factory.getDeserializer(cl); + } + + if (deserializer != null) { + } + + else if (Collection.class.isAssignableFrom(cl)) + deserializer = new CollectionDeserializer(cl); + + else if (Map.class.isAssignableFrom(cl)) + deserializer = new MapDeserializer(cl); + + else if (cl.isInterface()) + deserializer = new ObjectDeserializer(cl); + + else if (cl.isArray()) + deserializer = new ArrayDeserializer(cl.getComponentType()); + + else if (Enumeration.class.isAssignableFrom(cl)) + deserializer = EnumerationDeserializer.create(); + + else if (Enum.class.isAssignableFrom(cl)) + deserializer = new EnumDeserializer(cl); + + else if (Class.class.equals(cl)) + deserializer = new ClassDeserializer(_loader); + + else + deserializer = getDefaultDeserializer(cl); + + if (_cachedDeserializerMap == null) + _cachedDeserializerMap = new HashMap(8); + + synchronized (_cachedDeserializerMap) { + _cachedDeserializerMap.put(cl, deserializer); + } + + return deserializer; + } + + /** + * Returns the default serializer for a class that isn't matched + * directly. Application can override this method to produce + * bean-style serialization instead of field serialization. + * + * @param cl the class of the object that needs to be serialized. + * + * @return a serializer object for the serialization. + */ + protected Deserializer getDefaultDeserializer(Class cl) + { + return new JavaDeserializer(cl); + } + + /** + * Reads the object as a list. + */ + public Object readList(AbstractHessianInput in, int length, String type) + throws HessianProtocolException, IOException + { + Deserializer deserializer = getDeserializer(type); + + if (deserializer != null) + return deserializer.readList(in, length); + else + return new CollectionDeserializer(ArrayList.class).readList(in, length); + } + + /** + * Reads the object as a map. + */ + public Object readMap(AbstractHessianInput in, String type) + throws HessianProtocolException, IOException + { + Deserializer deserializer = getDeserializer(type); + + if (deserializer != null) + return deserializer.readMap(in); + else if (_hashMapDeserializer != null) + return _hashMapDeserializer.readMap(in); + else { + _hashMapDeserializer = new MapDeserializer(HashMap.class); + + return _hashMapDeserializer.readMap(in); + } + } + + /** + * Reads the object as a map. + */ + public Object readObject(AbstractHessianInput in, + String type, + String []fieldNames) + throws HessianProtocolException, IOException + { + Deserializer deserializer = getDeserializer(type); + + if (deserializer != null) + return deserializer.readObject(in, fieldNames); + else if (_hashMapDeserializer != null) + return _hashMapDeserializer.readObject(in, fieldNames); + else { + _hashMapDeserializer = new MapDeserializer(HashMap.class); + + return _hashMapDeserializer.readObject(in, fieldNames); + } + } + + /** + * Reads the object as a map. + */ + public Deserializer getObjectDeserializer(String type, Class cl) + throws HessianProtocolException + { + Deserializer reader = getObjectDeserializer(type); + + if (cl == null + || cl.equals(reader.getType()) + || cl.isAssignableFrom(reader.getType()) + || HessianHandle.class.isAssignableFrom(reader.getType())) { + return reader; + } + + if (log.isLoggable(Level.FINE)) { + log.fine("hessian: expected '" + cl.getName() + "' at '" + type + "' (" + + reader.getType().getName() + ")"); + } + + return getDeserializer(cl); + } + + /** + * Reads the object as a map. + */ + public Deserializer getObjectDeserializer(String type) + throws HessianProtocolException + { + Deserializer deserializer = getDeserializer(type); + + if (deserializer != null) + return deserializer; + else if (_hashMapDeserializer != null) + return _hashMapDeserializer; + else { + _hashMapDeserializer = new MapDeserializer(HashMap.class); + + return _hashMapDeserializer; + } + } + + /** + * Reads the object as a map. + */ + public Deserializer getListDeserializer(String type, Class cl) + throws HessianProtocolException + { + Deserializer reader = getListDeserializer(type); + + if (cl == null + || cl.equals(reader.getType()) + || cl.isAssignableFrom(reader.getType())) { + return reader; + } + + if (log.isLoggable(Level.FINE)) { + log.fine("hessian: expected '" + cl.getName() + "' at '" + type + "' (" + + reader.getType().getName() + ")"); + } + + return getDeserializer(cl); + } + + /** + * Reads the object as a map. + */ + public Deserializer getListDeserializer(String type) + throws HessianProtocolException + { + Deserializer deserializer = getDeserializer(type); + + if (deserializer != null) + return deserializer; + else if (_arrayListDeserializer != null) + return _arrayListDeserializer; + else { + _arrayListDeserializer = new CollectionDeserializer(ArrayList.class); + + return _arrayListDeserializer; + } + } + + /** + * Returns a deserializer based on a string type. + */ + public Deserializer getDeserializer(String type) + throws HessianProtocolException + { + if (type == null || type.equals("")) + return null; + + Deserializer deserializer; + + if (_cachedTypeDeserializerMap != null) { + synchronized (_cachedTypeDeserializerMap) { + deserializer = (Deserializer) _cachedTypeDeserializerMap.get(type); + } + + if (deserializer != null) + return deserializer; + } + + + deserializer = (Deserializer) _staticTypeMap.get(type); + if (deserializer != null) + return deserializer; + + if (type.startsWith("[")) { + Deserializer subDeserializer = getDeserializer(type.substring(1)); + + if (subDeserializer != null) + deserializer = new ArrayDeserializer(subDeserializer.getType()); + else + deserializer = new ArrayDeserializer(Object.class); + } + else { + try { + Class cl = Class.forName(type, false, _loader); + deserializer = getDeserializer(cl); + } catch (Exception e) { + log.warning("Hessian/Burlap: '" + type + "' is an unknown class in " + _loader + ":\n" + e); + + log.log(Level.FINER, e.toString(), e); + } + } + + if (deserializer != null) { + if (_cachedTypeDeserializerMap == null) + _cachedTypeDeserializerMap = new HashMap(8); + + synchronized (_cachedTypeDeserializerMap) { + _cachedTypeDeserializerMap.put(type, deserializer); + } + } + + return deserializer; + } + + private static void addBasic(Class cl, String typeName, int type) + { + _staticSerializerMap.put(cl, new BasicSerializer(type)); + + Deserializer deserializer = new BasicDeserializer(type); + _staticDeserializerMap.put(cl, deserializer); + _staticTypeMap.put(typeName, deserializer); + } + + static { + _staticSerializerMap = new HashMap(); + _staticDeserializerMap = new HashMap(); + _staticTypeMap = new HashMap(); + + addBasic(void.class, "void", BasicSerializer.NULL); + + addBasic(Boolean.class, "boolean", BasicSerializer.BOOLEAN); + addBasic(Byte.class, "byte", BasicSerializer.BYTE); + addBasic(Short.class, "short", BasicSerializer.SHORT); + addBasic(Integer.class, "int", BasicSerializer.INTEGER); + addBasic(Long.class, "long", BasicSerializer.LONG); + addBasic(Float.class, "float", BasicSerializer.FLOAT); + addBasic(Double.class, "double", BasicSerializer.DOUBLE); + addBasic(Character.class, "char", BasicSerializer.CHARACTER_OBJECT); + addBasic(String.class, "string", BasicSerializer.STRING); + addBasic(Object.class, "object", BasicSerializer.OBJECT); + addBasic(java.util.Date.class, "date", BasicSerializer.DATE); + + addBasic(boolean.class, "boolean", BasicSerializer.BOOLEAN); + addBasic(byte.class, "byte", BasicSerializer.BYTE); + addBasic(short.class, "short", BasicSerializer.SHORT); + addBasic(int.class, "int", BasicSerializer.INTEGER); + addBasic(long.class, "long", BasicSerializer.LONG); + addBasic(float.class, "float", BasicSerializer.FLOAT); + addBasic(double.class, "double", BasicSerializer.DOUBLE); + addBasic(char.class, "char", BasicSerializer.CHARACTER); + + addBasic(boolean[].class, "[boolean", BasicSerializer.BOOLEAN_ARRAY); + addBasic(byte[].class, "[byte", BasicSerializer.BYTE_ARRAY); + addBasic(short[].class, "[short", BasicSerializer.SHORT_ARRAY); + addBasic(int[].class, "[int", BasicSerializer.INTEGER_ARRAY); + addBasic(long[].class, "[long", BasicSerializer.LONG_ARRAY); + addBasic(float[].class, "[float", BasicSerializer.FLOAT_ARRAY); + addBasic(double[].class, "[double", BasicSerializer.DOUBLE_ARRAY); + addBasic(char[].class, "[char", BasicSerializer.CHARACTER_ARRAY); + addBasic(String[].class, "[string", BasicSerializer.STRING_ARRAY); + addBasic(Object[].class, "[object", BasicSerializer.OBJECT_ARRAY); + + _staticSerializerMap.put(Class.class, new ClassSerializer()); + + _staticDeserializerMap.put(Number.class, new BasicDeserializer(BasicSerializer.NUMBER)); + + _staticSerializerMap.put(BigDecimal.class, new StringValueSerializer()); + try { + _staticDeserializerMap.put(BigDecimal.class, + new StringValueDeserializer(BigDecimal.class)); + _staticDeserializerMap.put(BigInteger.class, + new BigIntegerDeserializer()); + } catch (Throwable e) { + } + + _staticSerializerMap.put(File.class, new StringValueSerializer()); + try { + _staticDeserializerMap.put(File.class, + new StringValueDeserializer(File.class)); + } catch (Throwable e) { + } + + _staticSerializerMap.put(ObjectName.class, new StringValueSerializer()); + try { + _staticDeserializerMap.put(ObjectName.class, + new StringValueDeserializer(ObjectName.class)); + } catch (Throwable e) { + } + + _staticSerializerMap.put(java.sql.Date.class, new SqlDateSerializer()); + _staticSerializerMap.put(java.sql.Time.class, new SqlDateSerializer()); + _staticSerializerMap.put(java.sql.Timestamp.class, new SqlDateSerializer()); + + _staticSerializerMap.put(java.io.InputStream.class, + new InputStreamSerializer()); + _staticDeserializerMap.put(java.io.InputStream.class, + new InputStreamDeserializer()); + + try { + _staticDeserializerMap.put(java.sql.Date.class, + new SqlDateDeserializer(java.sql.Date.class)); + _staticDeserializerMap.put(java.sql.Time.class, + new SqlDateDeserializer(java.sql.Time.class)); + _staticDeserializerMap.put(java.sql.Timestamp.class, + new SqlDateDeserializer(java.sql.Timestamp.class)); + } catch (Throwable e) { + e.printStackTrace(); + } + + // hessian/3bb5 + try { + Class stackTrace = StackTraceElement.class; + + _staticDeserializerMap.put(stackTrace, new StackTraceElementDeserializer()); + } catch (Throwable e) { + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/SqlDateDeserializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/SqlDateDeserializer.java new file mode 100644 index 000000000000..b23c7bb18dcb --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/SqlDateDeserializer.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.lang.reflect.Constructor; + +/** + * Deserializing a string valued object + */ +public class SqlDateDeserializer extends AbstractDeserializer { + private Class _cl; + private Constructor _constructor; + + public SqlDateDeserializer(Class cl) + throws NoSuchMethodException + { + _cl = cl; + _constructor = cl.getConstructor(new Class[] { long.class }); + } + + public Class getType() + { + return _cl; + } + + public Object readMap(AbstractHessianInput in) + throws IOException + { + int ref = in.addRef(null); + + long initValue = Long.MIN_VALUE; + + while (! in.isEnd()) { + String key = in.readString(); + + if (key.equals("value")) + initValue = in.readUTCDate(); + else + in.readString(); + } + + in.readMapEnd(); + + Object value = create(initValue); + + in.setRef(ref, value); + + return value; + } + + public Object readObject(AbstractHessianInput in, String []fieldNames) + throws IOException + { + int ref = in.addRef(null); + + long initValue = Long.MIN_VALUE; + + for (int i = 0; i < fieldNames.length; i++) { + String key = fieldNames[i]; + + if (key.equals("value")) + initValue = in.readUTCDate(); + else + in.readObject(); + } + + Object value = create(initValue); + + in.setRef(ref, value); + + return value; + } + + private Object create(long initValue) + throws IOException + { + if (initValue == Long.MIN_VALUE) + throw new IOException(_cl.getName() + " expects name."); + + try { + return _constructor.newInstance(new Object[] { new Long(initValue) }); + } catch (Exception e) { + throw new IOExceptionWrapper(e); + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/SqlDateSerializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/SqlDateSerializer.java new file mode 100644 index 000000000000..76bae3157108 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/SqlDateSerializer.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.util.Date; + +/** + * Serializing a sql date object. + */ +public class SqlDateSerializer extends AbstractSerializer +{ + public void writeObject(Object obj, AbstractHessianOutput out) + throws IOException + { + if (obj == null) + out.writeNull(); + else { + Class cl = obj.getClass(); + + if (out.addRef(obj)) + return; + + int ref = out.writeObjectBegin(cl.getName()); + + if (ref < -1) { + out.writeString("value"); + out.writeUTCDate(((Date) obj).getTime()); + out.writeMapEnd(); + } + else { + if (ref == -1) { + out.writeInt(1); + out.writeString("value"); + out.writeObjectBegin(cl.getName()); + } + + out.writeUTCDate(((Date) obj).getTime()); + } + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/StackTraceElementDeserializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/StackTraceElementDeserializer.java new file mode 100644 index 000000000000..1918d7321ed4 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/StackTraceElementDeserializer.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.*; +import java.util.HashMap; + +/** + * Deserializing a JDK 1.4 StackTraceElement + */ +public class StackTraceElementDeserializer extends JavaDeserializer { + public StackTraceElementDeserializer() + { + super(StackTraceElement.class); + } + + @Override + protected Object instantiate() + throws Exception + { + return new StackTraceElement("", "", "", 0); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/StringValueDeserializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/StringValueDeserializer.java new file mode 100644 index 000000000000..f142def6d80c --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/StringValueDeserializer.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; +import java.lang.reflect.Constructor; + +/** + * Deserializing a string valued object + */ +public class StringValueDeserializer extends AbstractDeserializer { + private Class _cl; + private Constructor _constructor; + + public StringValueDeserializer(Class cl) + { + try { + _cl = cl; + _constructor = cl.getConstructor(new Class[] { String.class }); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public Class getType() + { + return _cl; + } + + public Object readMap(AbstractHessianInput in) + throws IOException + { + String value = null; + + while (! in.isEnd()) { + String key = in.readString(); + + if (key.equals("value")) + value = in.readString(); + else + in.readObject(); + } + + in.readMapEnd(); + + Object object = create(value); + + in.addRef(object); + + return object; + } + + public Object readObject(AbstractHessianInput in, String []fieldNames) + throws IOException + { + String value = null; + + for (int i = 0; i < fieldNames.length; i++) { + if ("value".equals(fieldNames[i])) + value = in.readString(); + else + in.readObject(); + } + + Object object = create(value); + + in.addRef(object); + + return object; + } + + private Object create(String value) + throws IOException + { + if (value == null) + throw new IOException(_cl.getName() + " expects name."); + + try { + return _constructor.newInstance(new Object[] { value }); + } catch (Exception e) { + throw new IOExceptionWrapper(e); + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/StringValueSerializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/StringValueSerializer.java new file mode 100644 index 000000000000..0e04b0778828 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/StringValueSerializer.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; + +/** + * Serializing a remote object. + */ +public class StringValueSerializer extends AbstractSerializer { + public void writeObject(Object obj, AbstractHessianOutput out) + throws IOException + { + if (obj == null) + out.writeNull(); + else { + if (out.addRef(obj)) + return; + + Class cl = obj.getClass(); + + int ref = out.writeObjectBegin(cl.getName()); + + if (ref < -1) { + out.writeString("value"); + out.writeString(obj.toString()); + out.writeMapEnd(); + } + else { + if (ref == -1) { + out.writeInt(1); + out.writeString("value"); + out.writeObjectBegin(cl.getName()); + } + + out.writeString(obj.toString()); + } + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ThrowableSerializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ThrowableSerializer.java new file mode 100644 index 000000000000..391dc1bb0ff2 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ThrowableSerializer.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; + +/** + * Serializing an object for known object types. + */ +public class ThrowableSerializer extends JavaSerializer { + public ThrowableSerializer(Class cl, ClassLoader loader) + { + super(cl, loader); + } + + public void writeObject(Object obj, AbstractHessianOutput out) + throws IOException + { + Throwable e = (Throwable) obj; + + e.getStackTrace(); + + super.writeObject(obj, out); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ValueDeserializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ValueDeserializer.java new file mode 100644 index 000000000000..ba05a47c5d61 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/ValueDeserializer.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.io; + +import java.io.IOException; + +/** + * Deserializing a string valued object + */ +abstract public class ValueDeserializer extends AbstractDeserializer { + public Object readMap(AbstractHessianInput in) + throws IOException + { + String initValue = null; + + while (! in.isEnd()) { + String key = in.readString(); + + if (key.equals("value")) + initValue = in.readString(); + else + in.readObject(); + } + + in.readMapEnd(); + + return create(initValue); + } + + public Object readObject(AbstractHessianInput in, String []fieldNames) + throws IOException + { + String initValue = null; + + for (int i = 0; i < fieldNames.length; i++) { + if ("value".equals(fieldNames[i])) + initValue = in.readString(); + else + in.readObject(); + } + + return create(initValue); + } + + abstract Object create(String value) + throws IOException; +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/security/X509Encryption.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/security/X509Encryption.java new file mode 100644 index 000000000000..6a0b62211c11 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/security/X509Encryption.java @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.security; + +import java.security.*; +import java.security.cert.*; +import java.util.*; +import javax.crypto.*; + +import java.io.*; + +import com.alibaba.com.caucho.hessian.io.*; + +public class X509Encryption extends HessianEnvelope { + private String _algorithm = "AES"; + + // certificate for encryption/decryption + private X509Certificate _cert; + + // private key for decryption + private PrivateKey _privateKey; + + private SecureRandom _secureRandom; + + public X509Encryption() + { + } + + /** + * Sets the encryption algorithm for the content. + */ + public void setAlgorithm(String algorithm) + { + if (algorithm == null) + throw new NullPointerException(); + + _algorithm = algorithm; + } + + /** + * Gets the encryption algorithm for the content. + */ + public String getAlgorithm() + { + return _algorithm; + } + + /** + * The X509 certificate to obtain the public key of the recipient. + */ + public X509Certificate getCertificate() + { + return _cert; + } + + /** + * The X509 certificate to obtain the public key of the recipient. + */ + public void setCertificate(X509Certificate cert) + { + _cert = cert; + } + + /** + * The private key for decryption. + */ + public PrivateKey getPrivateKey() + { + return _privateKey; + } + + /** + * The X509 certificate to obtain the public key of the recipient. + */ + public void setPrivateKey(PrivateKey privateKey) + { + _privateKey = privateKey; + } + + /** + * The random number generator for the shared secrets. + */ + public SecureRandom getSecureRandom() + { + return _secureRandom; + } + + /** + * The random number generator for the shared secrets. + */ + public void setSecureRandom(SecureRandom random) + { + _secureRandom = random; + } + + public Hessian2Output wrap(Hessian2Output out) + throws IOException + { + if (_cert == null) + throw new IOException("X509Encryption.wrap requires a certificate"); + + OutputStream os = new EncryptOutputStream(out); + + Hessian2Output filterOut = new Hessian2Output(os); + + filterOut.setCloseStreamOnClose(true); + + return filterOut; + } + + public Hessian2Input unwrap(Hessian2Input in) + throws IOException + { + if (_privateKey == null) + throw new IOException("X509Encryption.unwrap requires a private key"); + + if (_cert == null) + throw new IOException("X509Encryption.unwrap requires a certificate"); + + int version = in.readEnvelope(); + + String method = in.readMethod(); + + if (! method.equals(getClass().getName())) + throw new IOException("expected hessian Envelope method '" + + getClass().getName() + "' at '" + method + "'"); + + return unwrapHeaders(in); + } + + public Hessian2Input unwrapHeaders(Hessian2Input in) + throws IOException + { + if (_privateKey == null) + throw new IOException("X509Encryption.unwrap requires a private key"); + + if (_cert == null) + throw new IOException("X509Encryption.unwrap requires a certificate"); + + InputStream is = new EncryptInputStream(in); + + Hessian2Input filter = new Hessian2Input(is); + + filter.setCloseStreamOnClose(true); + + return filter; + } + + class EncryptOutputStream extends OutputStream { + private Hessian2Output _out; + + private Cipher _cipher; + private OutputStream _bodyOut; + private CipherOutputStream _cipherOut; + + EncryptOutputStream(Hessian2Output out) + throws IOException + { + try { + _out = out; + + KeyGenerator keyGen = KeyGenerator.getInstance(_algorithm); + + if (_secureRandom != null) + keyGen.init(_secureRandom); + + SecretKey sharedKey = keyGen.generateKey(); + + _out = out; + + _out.startEnvelope(X509Encryption.class.getName()); + + PublicKey publicKey = _cert.getPublicKey(); + + byte []encoded = publicKey.getEncoded(); + MessageDigest md = MessageDigest.getInstance("SHA1"); + md.update(encoded); + byte []fingerprint = md.digest(); + + String keyAlgorithm = publicKey.getAlgorithm(); + Cipher keyCipher = Cipher.getInstance(keyAlgorithm); + if (_secureRandom != null) + keyCipher.init(Cipher.WRAP_MODE, _cert, _secureRandom); + else + keyCipher.init(Cipher.WRAP_MODE, _cert); + + byte []encKey = keyCipher.wrap(sharedKey); + + _out.writeInt(4); + + _out.writeString("algorithm"); + _out.writeString(_algorithm); + _out.writeString("fingerprint"); + _out.writeBytes(fingerprint); + _out.writeString("key-algorithm"); + _out.writeString(keyAlgorithm); + _out.writeString("key"); + _out.writeBytes(encKey); + + _bodyOut = _out.getBytesOutputStream(); + + _cipher = Cipher.getInstance(_algorithm); + if (_secureRandom != null) + _cipher.init(Cipher.ENCRYPT_MODE, sharedKey, _secureRandom); + else + _cipher.init(Cipher.ENCRYPT_MODE, sharedKey); + + _cipherOut = new CipherOutputStream(_bodyOut, _cipher); + } catch (RuntimeException e) { + throw e; + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public void write(int ch) + throws IOException + { + _cipherOut.write(ch); + } + + public void write(byte []buffer, int offset, int length) + throws IOException + { + _cipherOut.write(buffer, offset, length); + } + + public void close() + throws IOException + { + Hessian2Output out = _out; + _out = null; + + if (out != null) { + _cipherOut.close(); + _bodyOut.close(); + + out.writeInt(0); + out.completeEnvelope(); + out.close(); + } + } + } + + class EncryptInputStream extends InputStream { + private Hessian2Input _in; + + private Cipher _cipher; + private InputStream _bodyIn; + private CipherInputStream _cipherIn; + + EncryptInputStream(Hessian2Input in) + throws IOException + { + try { + _in = in; + + byte []fingerprint = null; + String keyAlgorithm = null; + String algorithm = null; + byte []encKey = null; + + int len = in.readInt(); + + for (int i = 0; i < len; i++) { + String header = in.readString(); + + if ("fingerprint".equals(header)) + fingerprint = in.readBytes(); + else if ("key-algorithm".equals(header)) + keyAlgorithm = in.readString(); + else if ("algorithm".equals(header)) + algorithm = in.readString(); + else if ("key".equals(header)) + encKey = in.readBytes(); + else + throw new IOException("'" + header + "' is an unexpected header"); + } + + Cipher keyCipher = Cipher.getInstance(keyAlgorithm); + keyCipher.init(Cipher.UNWRAP_MODE, _privateKey); + + Key key = keyCipher.unwrap(encKey, algorithm, Cipher.SECRET_KEY); + _bodyIn = _in.readInputStream(); + + _cipher = Cipher.getInstance(algorithm); + _cipher.init(Cipher.DECRYPT_MODE, key); + + _cipherIn = new CipherInputStream(_bodyIn, _cipher); + } catch (RuntimeException e) { + throw e; + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public int read() + throws IOException + { + return _cipherIn.read(); + } + + public int read(byte []buffer, int offset, int length) + throws IOException + { + return _cipherIn.read(buffer, offset, length); + } + + public void close() + throws IOException + { + Hessian2Input in = _in; + _in = null; + + if (in != null) { + _cipherIn.close(); + _bodyIn.close(); + + int len = in.readInt(); + + if (len != 0) + throw new IOException("Unexpected footer"); + + in.completeEnvelope(); + + in.close(); + } + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/security/X509Signature.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/security/X509Signature.java new file mode 100644 index 000000000000..77b19bb0435e --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/security/X509Signature.java @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Hessian", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.security; + +import java.security.*; +import java.security.cert.*; +import java.util.*; +import javax.crypto.*; + +import java.io.*; + +import com.alibaba.com.caucho.hessian.io.*; + +public class X509Signature extends HessianEnvelope { + private String _algorithm = "HmacSHA256"; + private X509Certificate _cert; + private PrivateKey _privateKey; + private SecureRandom _secureRandom; + + public X509Signature() + { + } + + /** + * Sets the encryption algorithm for the content. + */ + public void setAlgorithm(String algorithm) + { + if (algorithm == null) + throw new NullPointerException(); + + _algorithm = algorithm; + } + + /** + * Gets the encryption algorithm for the content. + */ + public String getAlgorithm() + { + return _algorithm; + } + + /** + * The X509 certificate to obtain the public key of the recipient. + */ + public X509Certificate getCertificate() + { + return _cert; + } + + /** + * The X509 certificate to obtain the public key of the recipient. + */ + public void setCertificate(X509Certificate cert) + { + _cert = cert; + } + + /** + * The key to obtain the private key of the recipient. + */ + public PrivateKey getPrivateKey() + { + return _privateKey; + } + + /** + * The private key. + */ + public void setPrivateKey(PrivateKey key) + { + _privateKey = key; + } + + /** + * The random number generator for the shared secrets. + */ + public SecureRandom getSecureRandom() + { + return _secureRandom; + } + + /** + * The random number generator for the shared secrets. + */ + public void setSecureRandom(SecureRandom random) + { + _secureRandom = random; + } + + public Hessian2Output wrap(Hessian2Output out) + throws IOException + { + if (_privateKey == null) + throw new IOException("X509Signature.wrap requires a private key"); + + if (_cert == null) + throw new IOException("X509Signature.wrap requires a certificate"); + + OutputStream os = new SignatureOutputStream(out); + + Hessian2Output filterOut = new Hessian2Output(os); + + filterOut.setCloseStreamOnClose(true); + + return filterOut; + } + + public Hessian2Input unwrap(Hessian2Input in) + throws IOException + { + if (_cert == null) + throw new IOException("X509Signature.unwrap requires a certificate"); + + int version = in.readEnvelope(); + + String method = in.readMethod(); + + if (! method.equals(getClass().getName())) + throw new IOException("expected hessian Envelope method '" + + getClass().getName() + "' at '" + method + "'"); + + return unwrapHeaders(in); + } + + public Hessian2Input unwrapHeaders(Hessian2Input in) + throws IOException + { + if (_cert == null) + throw new IOException("X509Signature.unwrap requires a certificate"); + + InputStream is = new SignatureInputStream(in); + + Hessian2Input filter = new Hessian2Input(is); + + filter.setCloseStreamOnClose(true); + + return filter; + } + + class SignatureOutputStream extends OutputStream { + private Hessian2Output _out; + private OutputStream _bodyOut; + private Mac _mac; + + SignatureOutputStream(Hessian2Output out) + throws IOException + { + try { + KeyGenerator keyGen = KeyGenerator.getInstance(_algorithm); + + if (_secureRandom != null) + keyGen.init(_secureRandom); + + SecretKey sharedKey = keyGen.generateKey(); + + _out = out; + + _out.startEnvelope(X509Signature.class.getName()); + + PublicKey publicKey = _cert.getPublicKey(); + + byte []encoded = publicKey.getEncoded(); + MessageDigest md = MessageDigest.getInstance("SHA1"); + md.update(encoded); + byte []fingerprint = md.digest(); + + String keyAlgorithm = _privateKey.getAlgorithm(); + Cipher keyCipher = Cipher.getInstance(keyAlgorithm); + keyCipher.init(Cipher.WRAP_MODE, _privateKey); + + byte []encKey = keyCipher.wrap(sharedKey); + + _out.writeInt(4); + _out.writeString("algorithm"); + _out.writeString(_algorithm); + _out.writeString("fingerprint"); + _out.writeBytes(fingerprint); + _out.writeString("key-algorithm"); + _out.writeString(keyAlgorithm); + _out.writeString("key"); + _out.writeBytes(encKey); + + _mac = Mac.getInstance(_algorithm); + _mac.init(sharedKey); + + _bodyOut = _out.getBytesOutputStream(); + } catch (RuntimeException e) { + throw e; + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public void write(int ch) + throws IOException + { + _bodyOut.write(ch); + _mac.update((byte) ch); + } + + public void write(byte []buffer, int offset, int length) + throws IOException + { + _bodyOut.write(buffer, offset, length); + _mac.update(buffer, offset, length); + } + + public void close() + throws IOException + { + Hessian2Output out = _out; + _out = null; + + if (out == null) + return; + + _bodyOut.close(); + + byte []sig = _mac.doFinal(); + + out.writeInt(1); + out.writeString("signature"); + out.writeBytes(sig); + + out.completeEnvelope(); + out.close(); + } + } + + class SignatureInputStream extends InputStream { + private Hessian2Input _in; + + private Mac _mac; + private InputStream _bodyIn; + private CipherInputStream _cipherIn; + + SignatureInputStream(Hessian2Input in) + throws IOException + { + try { + _in = in; + + byte []fingerprint = null; + String keyAlgorithm = null; + String algorithm = null; + byte []encKey = null; + + int len = in.readInt(); + + for (int i = 0; i < len; i++) { + String header = in.readString(); + + if ("fingerprint".equals(header)) + fingerprint = in.readBytes(); + else if ("key-algorithm".equals(header)) + keyAlgorithm = in.readString(); + else if ("algorithm".equals(header)) + algorithm = in.readString(); + else if ("key".equals(header)) + encKey = in.readBytes(); + else + throw new IOException("'" + header + "' is an unexpected header"); + } + + Cipher keyCipher = Cipher.getInstance(keyAlgorithm); + keyCipher.init(Cipher.UNWRAP_MODE, _cert); + + Key key = keyCipher.unwrap(encKey, algorithm, Cipher.SECRET_KEY); + _bodyIn = _in.readInputStream(); + + _mac = Mac.getInstance(algorithm); + _mac.init(key); + } catch (RuntimeException e) { + throw e; + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public int read() + throws IOException + { + int ch = _bodyIn.read(); + + if (ch < 0) + return ch; + + _mac.update((byte) ch); + + return ch; + } + + public int read(byte []buffer, int offset, int length) + throws IOException + { + int len = _bodyIn.read(buffer, offset, length); + + if (len < 0) + return len; + + _mac.update(buffer, offset, len); + + return len; + } + + public void close() + throws IOException + { + Hessian2Input in = _in; + _in = null; + + if (in != null) { + _bodyIn.close(); + + int len = in.readInt(); + byte []signature = null; + + for (int i = 0; i < len; i++) { + String header = in.readString(); + + if ("signature".equals(header)) + signature = in.readBytes(); + } + + in.completeEnvelope(); + in.close(); + + + if (signature == null) + throw new IOException("Expected signature"); + + byte []sig = _mac.doFinal(); + + if (sig.length != signature.length) + throw new IOException("mismatched signature"); + + for (int i = 0; i < sig.length; i++) { + if (signature[i] != sig[i]) + throw new IOException("mismatched signature"); + } + + // XXX: save principal + } + } + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/util/IdentityIntMap.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/util/IdentityIntMap.java new file mode 100644 index 000000000000..a17908952c7d --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/util/IdentityIntMap.java @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.util; + +/** + * The IntMap provides a simple hashmap from keys to integers. The API is + * an abbreviation of the HashMap collection API. + * + *

The convenience of IntMap is avoiding all the silly wrapping of + * integers. + */ +public class IdentityIntMap { + /** + * Encoding of a null entry. Since NULL is equal to Integer.MIN_VALUE, + * it's impossible to distinguish between the two. + */ + public final static int NULL = 0xdeadbeef; // Integer.MIN_VALUE + 1; + + private static final Object DELETED = new Object(); + + private Object []_keys; + private int []_values; + + private int _size; + private int _mask; + + /** + * Create a new IntMap. Default size is 16. + */ + public IdentityIntMap() + { + _keys = new Object[256]; + _values = new int[256]; + + _mask = _keys.length - 1; + _size = 0; + } + + /** + * Clear the hashmap. + */ + public void clear() + { + Object []keys = _keys; + int []values = _values; + + for (int i = keys.length - 1; i >= 0; i--) { + keys[i] = null; + values[i] = 0; + } + + _size = 0; + } + /** + * Returns the current number of entries in the map. + */ + public int size() + { + return _size; + } + + /** + * Puts a new value in the property table with the appropriate flags + */ + public int get(Object key) + { + int mask = _mask; + int hash = System.identityHashCode(key) % mask & mask; + + Object []keys = _keys; + + while (true) { + Object mapKey = keys[hash]; + + if (mapKey == null) + return NULL; + else if (mapKey == key) + return _values[hash]; + + hash = (hash + 1) % mask; + } + } + + /** + * Expands the property table + */ + private void resize(int newSize) + { + Object []newKeys = new Object[newSize]; + int []newValues = new int[newSize]; + + int mask = _mask = newKeys.length - 1; + + Object []keys = _keys; + int values[] = _values; + + for (int i = keys.length - 1; i >= 0; i--) { + Object key = keys[i]; + + if (key == null || key == DELETED) + continue; + + int hash = System.identityHashCode(key) % mask & mask; + + while (true) { + if (newKeys[hash] == null) { + newKeys[hash] = key; + newValues[hash] = values[i]; + break; + } + + hash = (hash + 1) % mask; + } + } + + _keys = newKeys; + _values = newValues; + } + + /** + * Puts a new value in the property table with the appropriate flags + */ + public int put(Object key, int value) + { + int mask = _mask; + int hash = System.identityHashCode(key) % mask & mask; + + Object []keys = _keys; + + while (true) { + Object testKey = keys[hash]; + + if (testKey == null || testKey == DELETED) { + keys[hash] = key; + _values[hash] = value; + + _size++; + + if (keys.length <= 4 * _size) + resize(4 * keys.length); + + return NULL; + } + else if (key != testKey) { + hash = (hash + 1) % mask; + + continue; + } + else { + int old = _values[hash]; + + _values[hash] = value; + + return old; + } + } + } + + /** + * Deletes the entry. Returns true if successful. + */ + public int remove(Object key) + { + int mask = _mask; + int hash = System.identityHashCode(key) % mask & mask; + + while (true) { + Object mapKey = _keys[hash]; + + if (mapKey == null) + return NULL; + else if (mapKey == key) { + _keys[hash] = DELETED; + + _size--; + + return _values[hash]; + } + + hash = (hash + 1) % mask; + } + } + + public String toString() + { + StringBuffer sbuf = new StringBuffer(); + + sbuf.append("IntMap["); + boolean isFirst = true; + + for (int i = 0; i <= _mask; i++) { + if (_keys[i] != null && _keys[i] != DELETED) { + if (! isFirst) + sbuf.append(", "); + + isFirst = false; + sbuf.append(_keys[i]); + sbuf.append(":"); + sbuf.append(_values[i]); + } + } + sbuf.append("]"); + + return sbuf.toString(); + } +} diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/util/IntMap.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/util/IntMap.java new file mode 100644 index 000000000000..c84bbd4dc571 --- /dev/null +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/util/IntMap.java @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. + * + * The Apache Software License, Version 1.1 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Caucho Technology (http://www.caucho.com/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "Burlap", "Resin", and "Caucho" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * info@caucho.com. + * + * 5. Products derived from this software may not be called "Resin" + * nor may "Resin" appear in their names without prior written + * permission of Caucho Technology. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Scott Ferguson + */ + +package com.alibaba.com.caucho.hessian.util; + +/** + * The IntMap provides a simple hashmap from keys to integers. The API is + * an abbreviation of the HashMap collection API. + * + *

The convenience of IntMap is avoiding all the silly wrapping of + * integers. + */ +public class IntMap { + /** + * Encoding of a null entry. Since NULL is equal to Integer.MIN_VALUE, + * it's impossible to distinguish between the two. + */ + public final static int NULL = 0xdeadbeef; // Integer.MIN_VALUE + 1; + + private static final Object DELETED = new Object(); + + private Object []_keys; + private int []_values; + + private int _size; + private int _mask; + + /** + * Create a new IntMap. Default size is 16. + */ + public IntMap() + { + _keys = new Object[256]; + _values = new int[256]; + + _mask = _keys.length - 1; + _size = 0; + } + + /** + * Clear the hashmap. + */ + public void clear() + { + Object []keys = _keys; + int []values = _values; + + for (int i = keys.length - 1; i >= 0; i--) { + keys[i] = null; + values[i] = 0; + } + + _size = 0; + } + /** + * Returns the current number of entries in the map. + */ + public int size() + { + return _size; + } + + /** + * Puts a new value in the property table with the appropriate flags + */ + public int get(Object key) + { + int mask = _mask; + int hash = key.hashCode() % mask & mask; + + Object []keys = _keys; + + while (true) { + Object mapKey = keys[hash]; + + if (mapKey == null) + return NULL; + else if (mapKey == key || mapKey.equals(key)) + return _values[hash]; + + hash = (hash + 1) % mask; + } + } + + /** + * Expands the property table + */ + private void resize(int newSize) + { + Object []newKeys = new Object[newSize]; + int []newValues = new int[newSize]; + + int mask = _mask = newKeys.length - 1; + + Object []keys = _keys; + int values[] = _values; + + for (int i = keys.length - 1; i >= 0; i--) { + Object key = keys[i]; + + if (key == null || key == DELETED) + continue; + + int hash = key.hashCode() % mask & mask; + + while (true) { + if (newKeys[hash] == null) { + newKeys[hash] = key; + newValues[hash] = values[i]; + break; + } + + hash = (hash + 1) % mask; + } + } + + _keys = newKeys; + _values = newValues; + } + + /** + * Puts a new value in the property table with the appropriate flags + */ + public int put(Object key, int value) + { + int mask = _mask; + int hash = key.hashCode() % mask & mask; + + Object []keys = _keys; + + while (true) { + Object testKey = keys[hash]; + + if (testKey == null || testKey == DELETED) { + keys[hash] = key; + _values[hash] = value; + + _size++; + + if (keys.length <= 4 * _size) + resize(4 * keys.length); + + return NULL; + } + else if (key != testKey && ! key.equals(testKey)) { + hash = (hash + 1) % mask; + + continue; + } + else { + int old = _values[hash]; + + _values[hash] = value; + + return old; + } + } + } + + /** + * Deletes the entry. Returns true if successful. + */ + public int remove(Object key) + { + int mask = _mask; + int hash = key.hashCode() % mask & mask; + + while (true) { + Object mapKey = _keys[hash]; + + if (mapKey == null) + return NULL; + else if (mapKey == key) { + _keys[hash] = DELETED; + + _size--; + + return _values[hash]; + } + + hash = (hash + 1) % mask; + } + } + + public String toString() + { + StringBuffer sbuf = new StringBuffer(); + + sbuf.append("IntMap["); + boolean isFirst = true; + + for (int i = 0; i <= _mask; i++) { + if (_keys[i] != null && _keys[i] != DELETED) { + if (! isFirst) + sbuf.append(", "); + + isFirst = false; + sbuf.append(_keys[i]); + sbuf.append(":"); + sbuf.append(_values[i]); + } + } + sbuf.append("]"); + + return sbuf.toString(); + } +} diff --git a/pom.xml b/pom.xml index 04194c562478..cb07bff9a292 100644 --- a/pom.xml +++ b/pom.xml @@ -1,12 +1,12 @@ + com.alibaba dubbo-parent - 2.4.3 + 2.8.4 pom ${project.artifactId} The parent project of dubbo @@ -51,9 +49,11 @@ dubbo-monitor dubbo-config dubbo - dubbo-simple - dubbo-admin - dubbo-demo + dubbo-simple + dubbo-admin + dubbo-demo + hessian-lite + @@ -84,27 +84,27 @@ - 2.5.6.SEC03 - 3.15.0-GA - 3.2.5.Final + 3.2.9.RELEASE + 3.20.0-GA + 3.7.0.Final 1.1.7 2.1.4 - 4.1.2 + 4.2.1 3.2.1-fixed-2 1.4.1 - 1.1.8 + 1.2.28 3.1 0.8 - 3.3.3 + 3.4.6 0.1 - 1.1.10 - 2.0.0 + 2.5.0 + 2.1.0 1.3.6 2.6.1 0.8.0 1.0.13 4.0.7 - 2.5 + 3.1.0 6.1.26 1.0.0.GA 4.2.0.Final @@ -113,6 +113,9 @@ 3.0 2.2 3.0.8 + 2.3.3 + 1.6 + 8.0.11 1.6.2 1.1 @@ -123,18 +126,47 @@ 3.0 0.999.8 - + false true ${file_encoding} + + + Copyright 1999-2012 Alibaba Group. Licensed 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. + oss + + + 2.3.2 + 1.6 + 1.6 + UTF-8 + + 2.1.1 + 2.3.2 + 2.1.1 + 2.3.1 + 2.7 + + 2.17 org.springframework - spring - ${spring_version} + spring-framework-bom + ${spring.bom.version} + pom + import org.javassist @@ -142,7 +174,7 @@ ${javassist_version} - org.jboss.netty + io.netty netty ${netty_version} @@ -197,7 +229,7 @@ ${zkclient_version} - com.netflix.curator + org.apache.curator curator-framework ${curator_version} @@ -238,7 +270,7 @@ javax.servlet - servlet-api + javax.servlet-api ${servlet_version} @@ -276,6 +308,16 @@ citrus-webx-all ${webx_version} + + com.fasterxml.jackson.core + jackson-core + ${jackson_version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson_version} + org.slf4j @@ -332,6 +374,73 @@ cglib-nodep ${cglib_version} + + commons-pool + commons-pool + ${commons_pool_version} + + + org.apache.tomcat.embed + tomcat-embed-core + ${tomcat_embed_version} + + + org.apache.tomcat.embed + tomcat-embed-logging-juli + ${tomcat_embed_version} + + + + + javax.ws.rs + javax.ws.rs-api + 2.0 + + + org.jboss.resteasy + resteasy-jaxrs + 3.0.7.Final + + + org.jboss.resteasy + resteasy-client + 3.0.7.Final + + + org.jboss.resteasy + resteasy-netty + 3.0.7.Final + + + org.jboss.resteasy + resteasy-jdk-http + 3.0.7.Final + + + org.jboss.resteasy + resteasy-jackson-provider + 3.0.7.Final + + + org.jboss.resteasy + resteasy-jaxb-provider + 3.0.7.Final + + + com.esotericsoftware.kryo + kryo + 2.24.0 + + + de.javakaffee + kryo-serializers + 0.26 + + + de.ruedigermoeller + fst + 1.55 + @@ -347,7 +456,7 @@ org.easymock easymockclassextension - + com.googlecode.jmockit jmockit @@ -368,9 +477,22 @@ + + maven-source-plugin + + + attach-sources + package + + jar-no-fork + + + + org.apache.maven.plugins maven-surefire-plugin + ${maven-surefire-plugin_version} true once @@ -446,19 +568,80 @@ + + + + + org.apache.maven.plugins + maven-jar-plugin + ${maven_jar_plugin_version} + + + org.apache.maven.plugins + maven-war-plugin + ${maven_war_plugin_version} + + + org.apache.maven.plugins + maven-install-plugin + ${maven_install_plugin_version} + + + org.apache.maven.plugins + maven-deploy-plugin + ${maven_deploy_plugin_version} + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven_compiler_plugin_version} + + true + ${java_source_version} + ${java_target_version} + ${file_encoding} + + -XX:MaxPermSize=512M + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + + org.apache.maven.plugins + + + maven-dependency-plugin + + + [2.1,) + + + unpack + + + + + + + + + + + + + - - - opensesame.releases - http://code.alibabatech.com/mvn/releases - - true - - - false - - - + jira http://code.alibabatech.com/jira/browse/DUBBO